blob: b96363151d88d6e581c5121d605697916fad521d [file] [log] [blame]
Jon Loeligerdebb7352006-04-26 17:58:56 -05001/*
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
79version_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
118Alignment:
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
136ProgramCheck:
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
182boot_cold:
183boot_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 */
1991: 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 sync
211 mtspr l2cr, r3
212#ifdef CONFIG_ALTIVEC
213 dssall
214#endif
215 /* invalidate the L2 cache */
216 bl l2cache_invalidate
217 sync
218#endif
219
220 /*
221 * Calculate absolute address in FLASH and jump there
222 *------------------------------------------------------*/
223 lis r3, CFG_MONITOR_BASE@h
224 ori r3, r3, CFG_MONITOR_BASE@l
225 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
226 mtlr r3
227 blr
228
229in_flash:
230 /* let the C-code set up the rest */
231 /* */
232 /* Be careful to keep code relocatable ! */
233 /*------------------------------------------------------*/
234 /* perform low-level init */
235
236 /* enable extended addressing */
237 bl enable_ext_addr
238
239 /* setup the bats */
240 bl setup_bats
241 sync
242
243#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
244 /* setup ccsrbar */
245 bl setup_ccsrbar
246#endif
247
248 /* setup the law entries */
249 bl law_entry
250 sync
251
252 /* Don't use this feature due to bug in 8641D PD4 */
253 /* Disable ERD_DIS */
254 lis r3, CFG_CCSRBAR@h
255 ori r3, r3, 0x1008
256 lwz r4, 0(r3)
257 oris r4, r4, 0x4000
258 stw r4, 0(r3)
259 sync
260
261#if (EMULATOR_RUN == 1)
262 /* On the emulator we want to adjust these ASAP */
263 /* otherwise things are sloooow */
264 /* Setup OR0 (LALE FIX)*/
265 lis r3, CFG_CCSRBAR@h
266 ori r3, r3, 0x5004
267 li r4, 0x0FF3
268 stw r4, 0(r3)
269 sync
270
271 /* Setup LCRR */
272 lis r3, CFG_CCSRBAR@h
273 ori r3, r3, 0x50D4
274 lis r4, 0x8000
275 ori r4, r4, 0x0002
276 stw r4, 0(r3)
277 sync
278#endif
279#if 1
280 /* make sure timer enabled in guts register too */
281 lis r3, CFG_CCSRBAR@h
282 oris r3,r3, 0xE
283 ori r3,r3,0x0070 /*Jason from 3*/
284 lwz r4, 0(r3)
285 lis r5,0xFFFC /*Jason from 0xffff*/
286 ori r5,r5,0x5FFF
287 and r4,r4,r5
288 stw r4,0(r3)
289#endif
290 /*
291 * Cache must be enabled here for stack-in-cache trick.
292 * This means we need to enable the BATS.
293 * Cache should be turned on after BATs, since by default
294 * everything is write-through.
295 */
296
297 /* enable address translation */
298 bl enable_addr_trans
299 sync
300
301 /* enable and invalidate the data cache */
302/* bl l1dcache_enable */
303 bl dcache_enable
304 sync
305
306#if 1
307 bl icache_enable
308#endif
309
310#ifdef CFG_INIT_RAM_LOCK
311 bl lock_ram_in_cache
312 sync
313#endif
314
315 /* set up the stack pointer in our newly created
316 * cache-ram (r1) */
317 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
318 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
319
320 li r0, 0 /* Make room for stack frame header and */
321 stwu r0, -4(r1) /* clear final stack frame so that */
322 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
323
324 GET_GOT /* initialize GOT access */
325
326 /* run low-level CPU init code (from Flash) */
327 bl cpu_init_f
328 sync
329
330#ifdef RUN_DIAG
331
332 /* Sri: Code to run the diagnostic automatically */
333
334 /* Load PX_AUX register address in r4 */
335 lis r4, 0xf810
336 ori r4, r4, 0x6
337 /* Load contents of PX_AUX in r3 bits 24 to 31*/
338 lbz r3, 0(r4)
339
340 /* Mask and obtain the bit in r3 */
341 rlwinm. r3, r3, 0, 24, 24
342 /* If not zero, jump and continue with u-boot */
343 bne diag_done
344
345 /* Load back contents of PX_AUX in r3 bits 24 to 31 */
346 lbz r3, 0(r4)
347 /* Set the MSB of the register value */
348 ori r3, r3, 0x80
349 /* Write value in r3 back to PX_AUX */
350 stb r3, 0(r4)
351
352 /* Get the address to jump to in r3*/
353 lis r3, CFG_DIAG_ADDR@h
354 ori r3, r3, CFG_DIAG_ADDR@l
355
356 /* Load the LR with the branch address */
357 mtlr r3
358
359 /* Branch to diagnostic */
360 blr
361
362diag_done:
363#endif
364
365 /* bl l2cache_enable*/
366 mr r3, r21
367
368 /* r3: BOOTFLAG */
369 /* run 1st part of board init code (from Flash) */
370 bl board_init_f
371 sync
372
373 /* NOTREACHED */
374
375 .globl invalidate_bats
376invalidate_bats:
377
378 /* invalidate BATs */
379 mtspr IBAT0U, r0
380 mtspr IBAT1U, r0
381 mtspr IBAT2U, r0
382 mtspr IBAT3U, r0
383 mtspr IBAT4U, r0
384 mtspr IBAT5U, r0
385 mtspr IBAT6U, r0
386 mtspr IBAT7U, r0
387
388 isync
389 mtspr DBAT0U, r0
390 mtspr DBAT1U, r0
391 mtspr DBAT2U, r0
392 mtspr DBAT3U, r0
393 mtspr DBAT4U, r0
394 mtspr DBAT5U, r0
395 mtspr DBAT6U, r0
396 mtspr DBAT7U, r0
397
398 isync
399 sync
400 blr
401
402
403 /* setup_bats - set them up to some initial state */
404 .globl setup_bats
405setup_bats:
406
407 addis r0, r0, 0x0000
408
409 /* IBAT 0 */
410 addis r4, r0, CFG_IBAT0L@h
411 ori r4, r4, CFG_IBAT0L@l
412 addis r3, r0, CFG_IBAT0U@h
413 ori r3, r3, CFG_IBAT0U@l
414 mtspr IBAT0L, r4
415 mtspr IBAT0U, r3
416 isync
417
418 /* DBAT 0 */
419 addis r4, r0, CFG_DBAT0L@h
420 ori r4, r4, CFG_DBAT0L@l
421 addis r3, r0, CFG_DBAT0U@h
422 ori r3, r3, CFG_DBAT0U@l
423 mtspr DBAT0L, r4
424 mtspr DBAT0U, r3
425 isync
426
427 /* IBAT 1 */
428 addis r4, r0, CFG_IBAT1L@h
429 ori r4, r4, CFG_IBAT1L@l
430 addis r3, r0, CFG_IBAT1U@h
431 ori r3, r3, CFG_IBAT1U@l
432 mtspr IBAT1L, r4
433 mtspr IBAT1U, r3
434 isync
435
436 /* DBAT 1 */
437 addis r4, r0, CFG_DBAT1L@h
438 ori r4, r4, CFG_DBAT1L@l
439 addis r3, r0, CFG_DBAT1U@h
440 ori r3, r3, CFG_DBAT1U@l
441 mtspr DBAT1L, r4
442 mtspr DBAT1U, r3
443 isync
444
445 /* IBAT 2 */
446 addis r4, r0, CFG_IBAT2L@h
447 ori r4, r4, CFG_IBAT2L@l
448 addis r3, r0, CFG_IBAT2U@h
449 ori r3, r3, CFG_IBAT2U@l
450 mtspr IBAT2L, r4
451 mtspr IBAT2U, r3
452 isync
453
454 /* DBAT 2 */
455 addis r4, r0, CFG_DBAT2L@h
456 ori r4, r4, CFG_DBAT2L@l
457 addis r3, r0, CFG_DBAT2U@h
458 ori r3, r3, CFG_DBAT2U@l
459 mtspr DBAT2L, r4
460 mtspr DBAT2U, r3
461 isync
462
463 /* IBAT 3 */
464 addis r4, r0, CFG_IBAT3L@h
465 ori r4, r4, CFG_IBAT3L@l
466 addis r3, r0, CFG_IBAT3U@h
467 ori r3, r3, CFG_IBAT3U@l
468 mtspr IBAT3L, r4
469 mtspr IBAT3U, r3
470 isync
471
472 /* DBAT 3 */
473 addis r4, r0, CFG_DBAT3L@h
474 ori r4, r4, CFG_DBAT3L@l
475 addis r3, r0, CFG_DBAT3U@h
476 ori r3, r3, CFG_DBAT3U@l
477 mtspr DBAT3L, r4
478 mtspr DBAT3U, r3
479 isync
480
481 /* IBAT 4 */
482 addis r4, r0, CFG_IBAT4L@h
483 ori r4, r4, CFG_IBAT4L@l
484 addis r3, r0, CFG_IBAT4U@h
485 ori r3, r3, CFG_IBAT4U@l
486 mtspr IBAT4L, r4
487 mtspr IBAT4U, r3
488 isync
489
490 /* DBAT 4 */
491 addis r4, r0, CFG_DBAT4L@h
492 ori r4, r4, CFG_DBAT4L@l
493 addis r3, r0, CFG_DBAT4U@h
494 ori r3, r3, CFG_DBAT4U@l
495 mtspr DBAT4L, r4
496 mtspr DBAT4U, r3
497 isync
498
499 /* IBAT 5 */
500 addis r4, r0, CFG_IBAT5L@h
501 ori r4, r4, CFG_IBAT5L@l
502 addis r3, r0, CFG_IBAT5U@h
503 ori r3, r3, CFG_IBAT5U@l
504 mtspr IBAT5L, r4
505 mtspr IBAT5U, r3
506 isync
507
508 /* DBAT 5 */
509 addis r4, r0, CFG_DBAT5L@h
510 ori r4, r4, CFG_DBAT5L@l
511 addis r3, r0, CFG_DBAT5U@h
512 ori r3, r3, CFG_DBAT5U@l
513 mtspr DBAT5L, r4
514 mtspr DBAT5U, r3
515 isync
516
517 /* IBAT 6 */
518 addis r4, r0, CFG_IBAT6L@h
519 ori r4, r4, CFG_IBAT6L@l
520 addis r3, r0, CFG_IBAT6U@h
521 ori r3, r3, CFG_IBAT6U@l
522 mtspr IBAT6L, r4
523 mtspr IBAT6U, r3
524 isync
525
526 /* DBAT 6 */
527 addis r4, r0, CFG_DBAT6L@h
528 ori r4, r4, CFG_DBAT6L@l
529 addis r3, r0, CFG_DBAT6U@h
530 ori r3, r3, CFG_DBAT6U@l
531 mtspr DBAT6L, r4
532 mtspr DBAT6U, r3
533 isync
534
535 /* IBAT 7 */
536 addis r4, r0, CFG_IBAT7L@h
537 ori r4, r4, CFG_IBAT7L@l
538 addis r3, r0, CFG_IBAT7U@h
539 ori r3, r3, CFG_IBAT7U@l
540 mtspr IBAT7L, r4
541 mtspr IBAT7U, r3
542 isync
543
544 /* DBAT 7 */
545 addis r4, r0, CFG_DBAT7L@h
546 ori r4, r4, CFG_DBAT7L@l
547 addis r3, r0, CFG_DBAT7U@h
548 ori r3, r3, CFG_DBAT7U@l
549 mtspr DBAT7L, r4
550 mtspr DBAT7U, r3
551 isync
552
5531:
554 addis r3, 0, 0x0000
555 addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
556 isync
557
558tlblp:
559 tlbie r3
560 sync
561 addi r3, r3, 0x1000
562 cmp 0, 0, r3, r5
563 blt tlblp
564
565 blr
566
567 .globl enable_addr_trans
568enable_addr_trans:
569 /* enable address translation */
570 mfmsr r5
571 ori r5, r5, (MSR_IR | MSR_DR)
572 mtmsr r5
573 isync
574 blr
575
576 .globl disable_addr_trans
577disable_addr_trans:
578 /* disable address translation */
579 mflr r4
580 mfmsr r3
581 andi. r0, r3, (MSR_IR | MSR_DR)
582 beqlr
583 andc r3, r3, r0
584 mtspr SRR0, r4
585 mtspr SRR1, r3
586 rfi
587
588/*
589 * This code finishes saving the registers to the exception frame
590 * and jumps to the appropriate handler for the exception.
591 * Register r21 is pointer into trap frame, r1 has new stack pointer.
592 */
593 .globl transfer_to_handler
594transfer_to_handler:
595 stw r22,_NIP(r21)
596 lis r22,MSR_POW@h
597 andc r23,r23,r22
598 stw r23,_MSR(r21)
599 SAVE_GPR(7, r21)
600 SAVE_4GPRS(8, r21)
601 SAVE_8GPRS(12, r21)
602 SAVE_8GPRS(24, r21)
603 mflr r23
604 andi. r24,r23,0x3f00 /* get vector offset */
605 stw r24,TRAP(r21)
606 li r22,0
607 stw r22,RESULT(r21)
608 mtspr SPRG2,r22 /* r1 is now kernel sp */
609 lwz r24,0(r23) /* virtual address of handler */
610 lwz r23,4(r23) /* where to go when done */
611 mtspr SRR0,r24
612 mtspr SRR1,r20
613 mtlr r23
614 SYNC
615 rfi /* jump to handler, enable MMU */
616
617int_return:
618 mfmsr r28 /* Disable interrupts */
619 li r4,0
620 ori r4,r4,MSR_EE
621 andc r28,r28,r4
622 SYNC /* Some chip revs need this... */
623 mtmsr r28
624 SYNC
625 lwz r2,_CTR(r1)
626 lwz r0,_LINK(r1)
627 mtctr r2
628 mtlr r0
629 lwz r2,_XER(r1)
630 lwz r0,_CCR(r1)
631 mtspr XER,r2
632 mtcrf 0xFF,r0
633 REST_10GPRS(3, r1)
634 REST_10GPRS(13, r1)
635 REST_8GPRS(23, r1)
636 REST_GPR(31, r1)
637 lwz r2,_NIP(r1) /* Restore environment */
638 lwz r0,_MSR(r1)
639 mtspr SRR0,r2
640 mtspr SRR1,r0
641 lwz r0,GPR0(r1)
642 lwz r2,GPR2(r1)
643 lwz r1,GPR1(r1)
644 SYNC
645 rfi
646
647 .globl dc_read
648dc_read:
649 blr
650
651 .globl get_pvr
652get_pvr:
653 mfspr r3, PVR
654 blr
655
656 .globl get_svr
657get_svr:
658 mfspr r3, SVR
659 blr
660
661
662/*------------------------------------------------------------------------------- */
663/* Function: in8 */
664/* Description: Input 8 bits */
665/*------------------------------------------------------------------------------- */
666 .globl in8
667in8:
668 lbz r3,0x0000(r3)
669 blr
670
671/*------------------------------------------------------------------------------- */
672/* Function: out8 */
673/* Description: Output 8 bits */
674/*------------------------------------------------------------------------------- */
675 .globl out8
676out8:
677 stb r4,0x0000(r3)
678 blr
679
680/*------------------------------------------------------------------------------- */
681/* Function: out16 */
682/* Description: Output 16 bits */
683/*------------------------------------------------------------------------------- */
684 .globl out16
685out16:
686 sth r4,0x0000(r3)
687 blr
688
689/*------------------------------------------------------------------------------- */
690/* Function: out16r */
691/* Description: Byte reverse and output 16 bits */
692/*------------------------------------------------------------------------------- */
693 .globl out16r
694out16r:
695 sthbrx r4,r0,r3
696 blr
697
698/*------------------------------------------------------------------------------- */
699/* Function: out32 */
700/* Description: Output 32 bits */
701/*------------------------------------------------------------------------------- */
702 .globl out32
703out32:
704 stw r4,0x0000(r3)
705 blr
706
707/*------------------------------------------------------------------------------- */
708/* Function: out32r */
709/* Description: Byte reverse and output 32 bits */
710/*------------------------------------------------------------------------------- */
711 .globl out32r
712out32r:
713 stwbrx r4,r0,r3
714 blr
715
716/*------------------------------------------------------------------------------- */
717/* Function: in16 */
718/* Description: Input 16 bits */
719/*------------------------------------------------------------------------------- */
720 .globl in16
721in16:
722 lhz r3,0x0000(r3)
723 blr
724
725/*------------------------------------------------------------------------------- */
726/* Function: in16r */
727/* Description: Input 16 bits and byte reverse */
728/*------------------------------------------------------------------------------- */
729 .globl in16r
730in16r:
731 lhbrx r3,r0,r3
732 blr
733
734/*------------------------------------------------------------------------------- */
735/* Function: in32 */
736/* Description: Input 32 bits */
737/*------------------------------------------------------------------------------- */
738 .globl in32
739in32:
740 lwz 3,0x0000(3)
741 blr
742
743/*------------------------------------------------------------------------------- */
744/* Function: in32r */
745/* Description: Input 32 bits and byte reverse */
746/*------------------------------------------------------------------------------- */
747 .globl in32r
748in32r:
749 lwbrx r3,r0,r3
750 blr
751
752/*------------------------------------------------------------------------------- */
753/* Function: ppcDcbf */
754/* Description: Data Cache block flush */
755/* Input: r3 = effective address */
756/* Output: none. */
757/*------------------------------------------------------------------------------- */
758 .globl ppcDcbf
759ppcDcbf:
760 dcbf r0,r3
761 blr
762
763/*------------------------------------------------------------------------------- */
764/* Function: ppcDcbi */
765/* Description: Data Cache block Invalidate */
766/* Input: r3 = effective address */
767/* Output: none. */
768/*------------------------------------------------------------------------------- */
769 .globl ppcDcbi
770ppcDcbi:
771 dcbi r0,r3
772 blr
773
774/*--------------------------------------------------------------------------
775 * Function: ppcDcbz
776 * Description: Data Cache block zero.
777 * Input: r3 = effective address
778 * Output: none.
779 *-------------------------------------------------------------------------- */
780
781 .globl ppcDcbz
782ppcDcbz:
783 dcbz r0,r3
784 blr
785
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500786/*-------------------------------------------------------------------------- */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500787/* Function: ppcSync */
788/* Description: Processor Synchronize */
789/* Input: none. */
790/* Output: none. */
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500791/*-------------------------------------------------------------------------- */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500792 .globl ppcSync
793ppcSync:
794 sync
795 blr
796
797/*-----------------------------------------------------------------------*/
798/*
799 * void relocate_code (addr_sp, gd, addr_moni)
800 *
801 * This "function" does not return, instead it continues in RAM
802 * after relocating the monitor code.
803 *
804 * r3 = dest
805 * r4 = src
806 * r5 = length in bytes
807 * r6 = cachelinesize
808 */
809 .globl relocate_code
810relocate_code:
811
812 mr r1, r3 /* Set new stack pointer */
813 mr r9, r4 /* Save copy of Global Data pointer */
814 mr r10, r5 /* Save copy of Destination Address */
815
816 mr r3, r5 /* Destination Address */
817 lis r4, CFG_MONITOR_BASE@h /* Source Address */
818 ori r4, r4, CFG_MONITOR_BASE@l
819 lwz r5, GOT(__init_end)
820 sub r5, r5, r4
821 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
822
823 /*
824 * Fix GOT pointer:
825 *
826 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
827 *
828 * Offset:
829 */
830 sub r15, r10, r4
831
832 /* First our own GOT */
833 add r14, r14, r15
834 /* then the one used by the C code */
835 add r30, r30, r15
836
837 /*
838 * Now relocate code
839 */
840#ifdef CONFIG_ECC
841 bl board_relocate_rom
842 sync
843 mr r3, r10 /* Destination Address */
844 lis r4, CFG_MONITOR_BASE@h /* Source Address */
845 ori r4, r4, CFG_MONITOR_BASE@l
846 lwz r5, GOT(__init_end)
847 sub r5, r5, r4
848 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
849#else
850 cmplw cr1,r3,r4
851 addi r0,r5,3
852 srwi. r0,r0,2
853 beq cr1,4f /* In place copy is not necessary */
854 beq 7f /* Protect against 0 count */
855 mtctr r0
856 bge cr1,2f
857
858 la r8,-4(r4)
859 la r7,-4(r3)
8601: lwzu r0,4(r8)
861 stwu r0,4(r7)
862 bdnz 1b
863 b 4f
864
8652: slwi r0,r0,2
866 add r8,r4,r0
867 add r7,r3,r0
8683: lwzu r0,-4(r8)
869 stwu r0,-4(r7)
870 bdnz 3b
871#endif
872/*
873 * Now flush the cache: note that we must start from a cache aligned
874 * address. Otherwise we might miss one cache line.
875 */
8764: cmpwi r6,0
877 add r5,r3,r5
878 beq 7f /* Always flush prefetch queue in any case */
879 subi r0,r6,1
880 andc r3,r3,r0
881 mr r4,r3
8825: dcbst 0,r4
883 add r4,r4,r6
884 cmplw r4,r5
885 blt 5b
886 sync /* Wait for all dcbst to complete on bus */
887 mr r4,r3
8886: icbi 0,r4
889 add r4,r4,r6
890 cmplw r4,r5
891 blt 6b
8927: sync /* Wait for all icbi to complete on bus */
893 isync
894
895/*
896 * We are done. Do not return, instead branch to second part of board
897 * initialization, now running from RAM.
898 */
899 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
900 mtlr r0
901 blr
902
903in_ram:
904#ifdef CONFIG_ECC
905 bl board_init_ecc
906#endif
907 /*
908 * Relocation Function, r14 point to got2+0x8000
909 *
910 * Adjust got2 pointers, no need to check for 0, this code
911 * already puts a few entries in the table.
912 */
913 li r0,__got2_entries@sectoff@l
914 la r3,GOT(_GOT2_TABLE_)
915 lwz r11,GOT(_GOT2_TABLE_)
916 mtctr r0
917 sub r11,r3,r11
918 addi r3,r3,-4
9191: lwzu r0,4(r3)
920 add r0,r0,r11
921 stw r0,0(r3)
922 bdnz 1b
923
924 /*
925 * Now adjust the fixups and the pointers to the fixups
926 * in case we need to move ourselves again.
927 */
9282: li r0,__fixup_entries@sectoff@l
929 lwz r3,GOT(_FIXUP_TABLE_)
930 cmpwi r0,0
931 mtctr r0
932 addi r3,r3,-4
933 beq 4f
9343: lwzu r4,4(r3)
935 lwzux r0,r4,r11
936 add r0,r0,r11
937 stw r10,0(r3)
938 stw r0,0(r4)
939 bdnz 3b
9404:
941/* clear_bss: */
942 /*
943 * Now clear BSS segment
944 */
945 lwz r3,GOT(__bss_start)
946 lwz r4,GOT(_end)
947
948 cmplw 0, r3, r4
949 beq 6f
950
951 li r0, 0
9525:
953 stw r0, 0(r3)
954 addi r3, r3, 4
955 cmplw 0, r3, r4
956 bne 5b
9576:
Haiying Wang6cfea332006-05-10 09:38:06 -0500958 mr r3, r9 /* Init Date pointer */
959 mr r4, r10 /* Destination Address */
960 bl board_init_r
Jon Loeligerdebb7352006-04-26 17:58:56 -0500961
962 /* not reached - end relocate_code */
963/*-----------------------------------------------------------------------*/
964
965 /*
966 * Copy exception vector code to low memory
967 *
968 * r3: dest_addr
969 * r7: source address, r8: end address, r9: target address
970 */
971 .globl trap_init
972trap_init:
973 lwz r7, GOT(_start)
974 lwz r8, GOT(_end_of_vectors)
975
976 li r9, 0x100 /* reset vector always at 0x100 */
977
978 cmplw 0, r7, r8
979 bgelr /* return if r7>=r8 - just in case */
980
981 mflr r4 /* save link register */
9821:
983 lwz r0, 0(r7)
984 stw r0, 0(r9)
985 addi r7, r7, 4
986 addi r9, r9, 4
987 cmplw 0, r7, r8
988 bne 1b
989
990 /*
991 * relocate `hdlr' and `int_return' entries
992 */
993 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
994 li r8, Alignment - _start + EXC_OFF_SYS_RESET
9952:
996 bl trap_reloc
997 addi r7, r7, 0x100 /* next exception vector */
998 cmplw 0, r7, r8
999 blt 2b
1000
1001 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1002 bl trap_reloc
1003
1004 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1005 bl trap_reloc
1006
1007 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1008 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
10093:
1010 bl trap_reloc
1011 addi r7, r7, 0x100 /* next exception vector */
1012 cmplw 0, r7, r8
1013 blt 3b
1014
1015 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1016 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
10174:
1018 bl trap_reloc
1019 addi r7, r7, 0x100 /* next exception vector */
1020 cmplw 0, r7, r8
1021 blt 4b
1022
1023 /* enable execptions from RAM vectors */
1024 mfmsr r7
1025 li r8,MSR_IP
1026 andc r7,r7,r8
1027 mtmsr r7
1028
1029 mtlr r4 /* restore link register */
1030 blr
1031
1032 /*
1033 * Function: relocate entries for one exception vector
1034 */
1035trap_reloc:
1036 lwz r0, 0(r7) /* hdlr ... */
1037 add r0, r0, r3 /* ... += dest_addr */
1038 stw r0, 0(r7)
1039
1040 lwz r0, 4(r7) /* int_return ... */
1041 add r0, r0, r3 /* ... += dest_addr */
1042 stw r0, 4(r7)
1043
1044 sync
1045 isync
1046
1047 blr
1048
1049.globl enable_ext_addr
1050enable_ext_addr:
1051 mfspr r0, HID0
1052 lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1053 ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1054 mtspr HID0, r0
1055 sync
1056 isync
1057 blr
1058
1059#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1060.globl setup_ccsrbar
1061setup_ccsrbar:
1062 /* Special sequence needed to update CCSRBAR itself */
1063 lis r4, CFG_CCSRBAR_DEFAULT@h
1064 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
1065
1066 lis r5, CFG_CCSRBAR@h
1067 ori r5, r5, CFG_CCSRBAR@l
1068 srwi r6,r5,12
1069 stw r6, 0(r4)
1070 isync
1071
1072 lis r5, 0xffff
1073 ori r5,r5,0xf000
1074 lwz r5, 0(r5)
1075 isync
1076
1077 lis r3, CFG_CCSRBAR@h
1078 lwz r5, CFG_CCSRBAR@l(r3)
1079 isync
1080
1081 blr
1082#endif
1083
1084#ifdef CFG_INIT_RAM_LOCK
1085lock_ram_in_cache:
1086 /* Allocate Initial RAM in data cache.
1087 */
1088 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1089 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1090 li r2, ((CFG_INIT_RAM_END & ~31) + \
1091 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1092 mtctr r2
10931:
1094 dcbz r0, r3
1095 addi r3, r3, 32
1096 bdnz 1b
1097#if 1
1098/* Lock the data cache */
1099 mfspr r0, HID0
1100 ori r0, r0, 0x1000
1101 sync
1102 mtspr HID0, r0
1103 sync
1104 blr
1105#endif
1106#if 0
1107 /* Lock the first way of the data cache */
1108 mfspr r0, LDSTCR
1109 ori r0, r0, 0x0080
1110#if defined(CONFIG_ALTIVEC)
1111 dssall
1112#endif
1113 sync
1114 mtspr LDSTCR, r0
1115 sync
1116 isync
1117 blr
1118#endif
1119
1120.globl unlock_ram_in_cache
1121unlock_ram_in_cache:
1122 /* invalidate the INIT_RAM section */
1123 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1124 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1125 li r2, ((CFG_INIT_RAM_END & ~31) + \
1126 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1127 mtctr r2
11281: icbi r0, r3
1129 addi r3, r3, 32
1130 bdnz 1b
1131 sync /* Wait for all icbi to complete on bus */
1132 isync
1133#if 1
1134/* Unlock the data cache and invalidate it */
1135 mfspr r0, HID0
1136 li r3,0x1000
1137 andc r0,r0,r3
1138 li r3,0x0400
1139 or r0,r0,r3
1140 sync
1141 mtspr HID0, r0
1142 sync
1143 blr
1144#endif
1145#if 0
1146 /* Unlock the first way of the data cache */
1147 mfspr r0, LDSTCR
1148 li r3,0x0080
1149 andc r0,r0,r3
1150#ifdef CONFIG_ALTIVEC
1151 dssall
1152#endif
1153 sync
1154 mtspr LDSTCR, r0
1155 sync
1156 isync
1157 li r3,0x0400
1158 or r0,r0,r3
1159 sync
1160 mtspr HID0, r0
1161 sync
1162 blr
1163#endif
1164#endif
1165
1166/* If this is a multi-cpu system then we need to handle the
1167 * 2nd cpu. The assumption is that the 2nd cpu is being
1168 * held in boot holdoff mode until the 1st cpu unlocks it
1169 * from Linux. We'll do some basic cpu init and then pass
1170 * it to the Linux Reset Vector.
1171 * Sri: Much of this initialization is not required. Linux
1172 * rewrites the bats, and the sprs and also enables the L1 cache.
1173 */
1174#if (CONFIG_NUM_CPUS > 1)
1175.globl secondary_cpu_setup
1176secondary_cpu_setup:
1177 /* Do only core setup on all cores except cpu0 */
1178 bl invalidate_bats
1179 sync
1180 bl enable_ext_addr
1181
1182#ifdef CFG_L2
1183 /* init the L2 cache */
1184 addis r3, r0, L2_INIT@h
1185 ori r3, r3, L2_INIT@l
1186 sync
1187 mtspr l2cr, r3
1188#ifdef CONFIG_ALTIVEC
1189 dssall
1190#endif
1191 /* invalidate the L2 cache */
1192 bl l2cache_invalidate
1193 sync
1194#endif
1195
1196 /* setup the bats */
1197 bl setup_bats
1198 sync
1199 /* enable address translation */
1200 bl enable_addr_trans
1201 sync
1202
1203 /* enable and invalidate the data cache */
1204 bl dcache_enable
1205 sync
1206
1207 /* enable and invalidate the instruction cache*/
1208 bl icache_enable
1209 sync
1210
1211 /* Set up MSR and HID0, HID1*/
1212 /* Enable interrupts */
1213/* mfmsr r28
1214 li r4,0
1215 ori r4,r4,MSR_EE
1216 or r28,r28,r4
1217 mtmsr r28
1218 */
1219
1220 /* TBEN in HID0 */
1221 mfspr r4, HID0
1222 oris r4, r4, 0x0400
1223 mtspr HID0, r4
1224 sync
1225 isync
1226
1227 /*SYNCBE|ABE in HID1*/
1228 mfspr r4, HID1
1229 ori r4, r4, 0x0C00
1230 mtspr HID1, r4
1231 sync
1232 isync
1233
1234 lis r3, CONFIG_LINUX_RESET_VEC@h
1235 ori r3, r3, CONFIG_LINUX_RESET_VEC@l
1236 mtlr r3
1237 blr
1238
1239 /* Never Returns, Running in Linux Now */
1240#endif
1241