blob: 07e75572b97a05433ad2483ac97f9c63e9f394cb [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
Jon Loeligerdebb7352006-04-26 17:58:56 -0500210 mtspr l2cr, r3
Jon Loeligerdebb7352006-04-26 17:58:56 -0500211 /* 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
225in_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
Jon Loeliger14e37082006-05-19 13:28:39 -0500244 /* 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
Jon Loeligerdebb7352006-04-26 17:58:56 -0500251 /* 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
Jon Loeliger14e37082006-05-19 13:28:39 -0500286 ori r3,r3,0x0070
Jon Loeligerdebb7352006-04-26 17:58:56 -0500287 lwz r4, 0(r3)
Jon Loeliger14e37082006-05-19 13:28:39 -0500288 lis r5,0xFFFC
Jon Loeligerdebb7352006-04-26 17:58:56 -0500289 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
365diag_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
379invalidate_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
408setup_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
5561:
557 addis r3, 0, 0x0000
558 addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
559 isync
560
561tlblp:
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
571enable_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
580disable_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
597transfer_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
620int_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
651dc_read:
652 blr
653
654 .globl get_pvr
655get_pvr:
656 mfspr r3, PVR
657 blr
658
659 .globl get_svr
660get_svr:
661 mfspr r3, SVR
662 blr
663
664
665/*------------------------------------------------------------------------------- */
666/* Function: in8 */
667/* Description: Input 8 bits */
668/*------------------------------------------------------------------------------- */
669 .globl in8
670in8:
671 lbz r3,0x0000(r3)
672 blr
673
674/*------------------------------------------------------------------------------- */
675/* Function: out8 */
676/* Description: Output 8 bits */
677/*------------------------------------------------------------------------------- */
678 .globl out8
679out8:
680 stb r4,0x0000(r3)
681 blr
682
683/*------------------------------------------------------------------------------- */
684/* Function: out16 */
685/* Description: Output 16 bits */
686/*------------------------------------------------------------------------------- */
687 .globl out16
688out16:
689 sth r4,0x0000(r3)
690 blr
691
692/*------------------------------------------------------------------------------- */
693/* Function: out16r */
694/* Description: Byte reverse and output 16 bits */
695/*------------------------------------------------------------------------------- */
696 .globl out16r
697out16r:
698 sthbrx r4,r0,r3
699 blr
700
701/*------------------------------------------------------------------------------- */
702/* Function: out32 */
703/* Description: Output 32 bits */
704/*------------------------------------------------------------------------------- */
705 .globl out32
706out32:
707 stw r4,0x0000(r3)
708 blr
709
710/*------------------------------------------------------------------------------- */
711/* Function: out32r */
712/* Description: Byte reverse and output 32 bits */
713/*------------------------------------------------------------------------------- */
714 .globl out32r
715out32r:
716 stwbrx r4,r0,r3
717 blr
718
719/*------------------------------------------------------------------------------- */
720/* Function: in16 */
721/* Description: Input 16 bits */
722/*------------------------------------------------------------------------------- */
723 .globl in16
724in16:
725 lhz r3,0x0000(r3)
726 blr
727
728/*------------------------------------------------------------------------------- */
729/* Function: in16r */
730/* Description: Input 16 bits and byte reverse */
731/*------------------------------------------------------------------------------- */
732 .globl in16r
733in16r:
734 lhbrx r3,r0,r3
735 blr
736
737/*------------------------------------------------------------------------------- */
738/* Function: in32 */
739/* Description: Input 32 bits */
740/*------------------------------------------------------------------------------- */
741 .globl in32
742in32:
743 lwz 3,0x0000(3)
744 blr
745
746/*------------------------------------------------------------------------------- */
747/* Function: in32r */
748/* Description: Input 32 bits and byte reverse */
749/*------------------------------------------------------------------------------- */
750 .globl in32r
751in32r:
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
762ppcDcbf:
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
773ppcDcbi:
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
784 .globl ppcDcbz
785ppcDcbz:
786 dcbz r0,r3
787 blr
788
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500789/*-------------------------------------------------------------------------- */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500790/* Function: ppcSync */
791/* Description: Processor Synchronize */
792/* Input: none. */
793/* Output: none. */
Jon Loeliger5c9efb32006-04-27 10:15:16 -0500794/*-------------------------------------------------------------------------- */
Jon Loeligerdebb7352006-04-26 17:58:56 -0500795 .globl ppcSync
796ppcSync:
797 sync
798 blr
799
800/*-----------------------------------------------------------------------*/
801/*
802 * void relocate_code (addr_sp, gd, addr_moni)
803 *
804 * This "function" does not return, instead it continues in RAM
805 * after relocating the monitor code.
806 *
807 * r3 = dest
808 * r4 = src
809 * r5 = length in bytes
810 * r6 = cachelinesize
811 */
812 .globl relocate_code
813relocate_code:
814
815 mr r1, r3 /* Set new stack pointer */
816 mr r9, r4 /* Save copy of Global Data pointer */
817 mr r10, r5 /* Save copy of Destination Address */
818
819 mr r3, r5 /* Destination Address */
820 lis r4, CFG_MONITOR_BASE@h /* Source Address */
821 ori r4, r4, CFG_MONITOR_BASE@l
822 lwz r5, GOT(__init_end)
823 sub r5, r5, r4
824 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
825
826 /*
827 * Fix GOT pointer:
828 *
829 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
830 *
831 * Offset:
832 */
833 sub r15, r10, r4
834
835 /* First our own GOT */
836 add r14, r14, r15
837 /* then the one used by the C code */
838 add r30, r30, r15
839
840 /*
841 * Now relocate code
842 */
843#ifdef CONFIG_ECC
844 bl board_relocate_rom
845 sync
846 mr r3, r10 /* Destination Address */
847 lis r4, CFG_MONITOR_BASE@h /* Source Address */
848 ori r4, r4, CFG_MONITOR_BASE@l
849 lwz r5, GOT(__init_end)
850 sub r5, r5, r4
851 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
852#else
853 cmplw cr1,r3,r4
854 addi r0,r5,3
855 srwi. r0,r0,2
856 beq cr1,4f /* In place copy is not necessary */
857 beq 7f /* Protect against 0 count */
858 mtctr r0
859 bge cr1,2f
860
861 la r8,-4(r4)
862 la r7,-4(r3)
8631: lwzu r0,4(r8)
864 stwu r0,4(r7)
865 bdnz 1b
866 b 4f
867
8682: slwi r0,r0,2
869 add r8,r4,r0
870 add r7,r3,r0
8713: lwzu r0,-4(r8)
872 stwu r0,-4(r7)
873 bdnz 3b
874#endif
875/*
876 * Now flush the cache: note that we must start from a cache aligned
877 * address. Otherwise we might miss one cache line.
878 */
8794: cmpwi r6,0
880 add r5,r3,r5
881 beq 7f /* Always flush prefetch queue in any case */
882 subi r0,r6,1
883 andc r3,r3,r0
884 mr r4,r3
8855: dcbst 0,r4
886 add r4,r4,r6
887 cmplw r4,r5
888 blt 5b
889 sync /* Wait for all dcbst to complete on bus */
890 mr r4,r3
8916: icbi 0,r4
892 add r4,r4,r6
893 cmplw r4,r5
894 blt 6b
8957: sync /* Wait for all icbi to complete on bus */
896 isync
897
898/*
899 * We are done. Do not return, instead branch to second part of board
900 * initialization, now running from RAM.
901 */
902 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
903 mtlr r0
904 blr
905
906in_ram:
907#ifdef CONFIG_ECC
908 bl board_init_ecc
909#endif
910 /*
911 * Relocation Function, r14 point to got2+0x8000
912 *
913 * Adjust got2 pointers, no need to check for 0, this code
914 * already puts a few entries in the table.
915 */
916 li r0,__got2_entries@sectoff@l
917 la r3,GOT(_GOT2_TABLE_)
918 lwz r11,GOT(_GOT2_TABLE_)
919 mtctr r0
920 sub r11,r3,r11
921 addi r3,r3,-4
9221: lwzu r0,4(r3)
923 add r0,r0,r11
924 stw r0,0(r3)
925 bdnz 1b
926
927 /*
928 * Now adjust the fixups and the pointers to the fixups
929 * in case we need to move ourselves again.
930 */
9312: li r0,__fixup_entries@sectoff@l
932 lwz r3,GOT(_FIXUP_TABLE_)
933 cmpwi r0,0
934 mtctr r0
935 addi r3,r3,-4
936 beq 4f
9373: lwzu r4,4(r3)
938 lwzux r0,r4,r11
939 add r0,r0,r11
940 stw r10,0(r3)
941 stw r0,0(r4)
942 bdnz 3b
9434:
944/* clear_bss: */
945 /*
946 * Now clear BSS segment
947 */
948 lwz r3,GOT(__bss_start)
949 lwz r4,GOT(_end)
950
951 cmplw 0, r3, r4
952 beq 6f
953
954 li r0, 0
9555:
956 stw r0, 0(r3)
957 addi r3, r3, 4
958 cmplw 0, r3, r4
959 bne 5b
9606:
Haiying Wang6cfea332006-05-10 09:38:06 -0500961 mr r3, r9 /* Init Date pointer */
962 mr r4, r10 /* Destination Address */
963 bl board_init_r
Jon Loeligerdebb7352006-04-26 17:58:56 -0500964
965 /* not reached - end relocate_code */
966/*-----------------------------------------------------------------------*/
967
968 /*
969 * Copy exception vector code to low memory
970 *
971 * r3: dest_addr
972 * r7: source address, r8: end address, r9: target address
973 */
974 .globl trap_init
975trap_init:
976 lwz r7, GOT(_start)
977 lwz r8, GOT(_end_of_vectors)
978
979 li r9, 0x100 /* reset vector always at 0x100 */
980
981 cmplw 0, r7, r8
982 bgelr /* return if r7>=r8 - just in case */
983
984 mflr r4 /* save link register */
9851:
986 lwz r0, 0(r7)
987 stw r0, 0(r9)
988 addi r7, r7, 4
989 addi r9, r9, 4
990 cmplw 0, r7, r8
991 bne 1b
992
993 /*
994 * relocate `hdlr' and `int_return' entries
995 */
996 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
997 li r8, Alignment - _start + EXC_OFF_SYS_RESET
9982:
999 bl trap_reloc
1000 addi r7, r7, 0x100 /* next exception vector */
1001 cmplw 0, r7, r8
1002 blt 2b
1003
1004 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1005 bl trap_reloc
1006
1007 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1008 bl trap_reloc
1009
1010 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1011 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
10123:
1013 bl trap_reloc
1014 addi r7, r7, 0x100 /* next exception vector */
1015 cmplw 0, r7, r8
1016 blt 3b
1017
1018 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1019 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
10204:
1021 bl trap_reloc
1022 addi r7, r7, 0x100 /* next exception vector */
1023 cmplw 0, r7, r8
1024 blt 4b
1025
1026 /* enable execptions from RAM vectors */
1027 mfmsr r7
1028 li r8,MSR_IP
1029 andc r7,r7,r8
1030 mtmsr r7
1031
1032 mtlr r4 /* restore link register */
1033 blr
1034
1035 /*
1036 * Function: relocate entries for one exception vector
1037 */
1038trap_reloc:
1039 lwz r0, 0(r7) /* hdlr ... */
1040 add r0, r0, r3 /* ... += dest_addr */
1041 stw r0, 0(r7)
1042
1043 lwz r0, 4(r7) /* int_return ... */
1044 add r0, r0, r3 /* ... += dest_addr */
1045 stw r0, 4(r7)
1046
1047 sync
1048 isync
1049
1050 blr
1051
1052.globl enable_ext_addr
1053enable_ext_addr:
1054 mfspr r0, HID0
1055 lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1056 ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1057 mtspr HID0, r0
1058 sync
1059 isync
1060 blr
1061
1062#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1063.globl setup_ccsrbar
1064setup_ccsrbar:
1065 /* Special sequence needed to update CCSRBAR itself */
1066 lis r4, CFG_CCSRBAR_DEFAULT@h
1067 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
1068
1069 lis r5, CFG_CCSRBAR@h
1070 ori r5, r5, CFG_CCSRBAR@l
1071 srwi r6,r5,12
1072 stw r6, 0(r4)
1073 isync
1074
1075 lis r5, 0xffff
1076 ori r5,r5,0xf000
1077 lwz r5, 0(r5)
1078 isync
1079
1080 lis r3, CFG_CCSRBAR@h
1081 lwz r5, CFG_CCSRBAR@l(r3)
1082 isync
1083
1084 blr
1085#endif
1086
1087#ifdef CFG_INIT_RAM_LOCK
1088lock_ram_in_cache:
1089 /* Allocate Initial RAM in data cache.
1090 */
1091 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1092 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1093 li r2, ((CFG_INIT_RAM_END & ~31) + \
1094 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1095 mtctr r2
10961:
1097 dcbz r0, r3
1098 addi r3, r3, 32
1099 bdnz 1b
1100#if 1
1101/* Lock the data cache */
1102 mfspr r0, HID0
1103 ori r0, r0, 0x1000
1104 sync
1105 mtspr HID0, r0
1106 sync
1107 blr
1108#endif
1109#if 0
1110 /* Lock the first way of the data cache */
1111 mfspr r0, LDSTCR
1112 ori r0, r0, 0x0080
1113#if defined(CONFIG_ALTIVEC)
1114 dssall
1115#endif
1116 sync
1117 mtspr LDSTCR, r0
1118 sync
1119 isync
1120 blr
1121#endif
1122
1123.globl unlock_ram_in_cache
1124unlock_ram_in_cache:
1125 /* invalidate the INIT_RAM section */
1126 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1127 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1128 li r2, ((CFG_INIT_RAM_END & ~31) + \
1129 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1130 mtctr r2
11311: icbi r0, r3
1132 addi r3, r3, 32
1133 bdnz 1b
1134 sync /* Wait for all icbi to complete on bus */
1135 isync
1136#if 1
1137/* Unlock the data cache and invalidate it */
1138 mfspr r0, HID0
1139 li r3,0x1000
1140 andc r0,r0,r3
1141 li r3,0x0400
1142 or r0,r0,r3
1143 sync
1144 mtspr HID0, r0
1145 sync
1146 blr
1147#endif
1148#if 0
1149 /* Unlock the first way of the data cache */
1150 mfspr r0, LDSTCR
1151 li r3,0x0080
1152 andc r0,r0,r3
1153#ifdef CONFIG_ALTIVEC
1154 dssall
1155#endif
1156 sync
1157 mtspr LDSTCR, r0
1158 sync
1159 isync
1160 li r3,0x0400
1161 or r0,r0,r3
1162 sync
1163 mtspr HID0, r0
1164 sync
1165 blr
1166#endif
1167#endif
1168
1169/* If this is a multi-cpu system then we need to handle the
1170 * 2nd cpu. The assumption is that the 2nd cpu is being
1171 * held in boot holdoff mode until the 1st cpu unlocks it
1172 * from Linux. We'll do some basic cpu init and then pass
1173 * it to the Linux Reset Vector.
1174 * Sri: Much of this initialization is not required. Linux
1175 * rewrites the bats, and the sprs and also enables the L1 cache.
1176 */
1177#if (CONFIG_NUM_CPUS > 1)
1178.globl secondary_cpu_setup
1179secondary_cpu_setup:
1180 /* Do only core setup on all cores except cpu0 */
1181 bl invalidate_bats
1182 sync
1183 bl enable_ext_addr
1184
1185#ifdef CFG_L2
1186 /* init the L2 cache */
1187 addis r3, r0, L2_INIT@h
1188 ori r3, r3, L2_INIT@l
1189 sync
1190 mtspr l2cr, r3
1191#ifdef CONFIG_ALTIVEC
1192 dssall
1193#endif
1194 /* invalidate the L2 cache */
1195 bl l2cache_invalidate
1196 sync
1197#endif
1198
1199 /* setup the bats */
1200 bl setup_bats
1201 sync
1202 /* enable address translation */
1203 bl enable_addr_trans
1204 sync
1205
1206 /* enable and invalidate the data cache */
1207 bl dcache_enable
1208 sync
1209
1210 /* enable and invalidate the instruction cache*/
1211 bl icache_enable
1212 sync
1213
1214 /* Set up MSR and HID0, HID1*/
1215 /* Enable interrupts */
1216/* mfmsr r28
1217 li r4,0
1218 ori r4,r4,MSR_EE
1219 or r28,r28,r4
1220 mtmsr r28
1221 */
1222
1223 /* TBEN in HID0 */
1224 mfspr r4, HID0
1225 oris r4, r4, 0x0400
1226 mtspr HID0, r4
1227 sync
1228 isync
1229
1230 /*SYNCBE|ABE in HID1*/
1231 mfspr r4, HID1
1232 ori r4, r4, 0x0C00
1233 mtspr HID1, r4
1234 sync
1235 isync
1236
1237 lis r3, CONFIG_LINUX_RESET_VEC@h
1238 ori r3, r3, CONFIG_LINUX_RESET_VEC@l
1239 mtlr r3
1240 blr
1241
1242 /* Never Returns, Running in Linux Now */
1243#endif
1244