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