blob: 040b88deebf1613a2588a597bb420a6ad92e5288 [file] [log] [blame]
wdenk42d1f032003-10-15 23:53:47 +00001/*
wdenk97d80fc2004-06-09 00:34:46 +00002 * Copyright 2004 Freescale Semiconductor.
wdenk42d1f032003-10-15 23:53:47 +00003 * Copyright (C) 2003 Motorola,Inc.
4 * Xianghua Xiao<X.Xiao@motorola.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25/* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
26 *
27 * The processor starts at 0xfffffffc and the code is first executed in the
28 * last 4K page(0xfffff000-0xffffffff) in flash/rom.
29 *
30 */
31
32#include <config.h>
33#include <mpc85xx.h>
34#include <version.h>
35
36#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
37
38#include <ppc_asm.tmpl>
39#include <ppc_defs.h>
40
41#include <asm/cache.h>
42#include <asm/mmu.h>
43
44#ifndef CONFIG_IDENT_STRING
45#define CONFIG_IDENT_STRING ""
46#endif
47
48#undef MSR_KERNEL
49#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
50
51/*
52 * Set up GOT: Global Offset Table
53 *
54 * Use r14 to access the GOT
55 */
56 START_GOT
57 GOT_ENTRY(_GOT2_TABLE_)
58 GOT_ENTRY(_FIXUP_TABLE_)
59
60 GOT_ENTRY(_start)
61 GOT_ENTRY(_start_of_vectors)
62 GOT_ENTRY(_end_of_vectors)
63 GOT_ENTRY(transfer_to_handler)
64
65 GOT_ENTRY(__init_end)
66 GOT_ENTRY(_end)
67 GOT_ENTRY(__bss_start)
68 END_GOT
69
70/*
71 * e500 Startup -- after reset only the last 4KB of the effective
72 * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
73 * section is located at THIS LAST page and basically does three
74 * things: clear some registers, set up exception tables and
75 * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
76 * continue the boot procedure.
77
78 * Once the boot rom is mapped by TLB entries we can proceed
79 * with normal startup.
80 *
81 */
82
83 .section .bootpg,"ax"
84 .globl _start_e500
85
86_start_e500:
wdenk97d80fc2004-06-09 00:34:46 +000087 mfspr r0, PVR
88 lis r1, PVR_85xx_REV1@h
89 ori r1, r1, PVR_85xx_REV1@l
90 cmpw r0, r1
91 bne 1f
92
93 /* Semi-bogus errata fixup for Rev 1 */
wdenk42d1f032003-10-15 23:53:47 +000094 li r0,0x2000
95 mtspr 977,r0
wdenk42d1f032003-10-15 23:53:47 +000096
wdenk97d80fc2004-06-09 00:34:46 +000097 /*
98 * Before invalidating MMU L1/L2, read TLB1 Entry 0 and then
99 * write it back immediately to fixup a Rev 1 bug (Errata CPU4)
100 * for this initial TLB1 entry 0, otherwise the TLB1 entry 0
101 * will be invalidated (incorrectly).
102 */
103 lis r2,0x1000
104 mtspr MAS0,r2
105 tlbre
106 tlbwe
107 isync
108
1091:
110 /*
111 * Clear and set up some registers.
112 * Note: Some registers need strict synchronization by
113 * sync/mbar/msync/isync when being "mtspr".
wdenk42d1f032003-10-15 23:53:47 +0000114 * BookE: isync before PID,tlbivax,tlbwe
115 * BookE: isync after MSR,PID; msync_isync after tlbivax & tlbwe
116 * E500: msync,isync before L1CSR0
wdenk97d80fc2004-06-09 00:34:46 +0000117 * E500: isync after BBEAR,BBTAR,BUCSR,DBCR0,DBCR1,HID0,HID1,
118 * L1CSR0, L1CSR1, MAS[0,1,2,3,4,6],MMUCSR0, PID[0,1,2],
119 * SPEFCSR
wdenk42d1f032003-10-15 23:53:47 +0000120 */
121
122 /* invalidate d-cache */
123 mfspr r0,L1CSR0
124 ori r0,r0,0x0002
125 msync
126 isync
127 mtspr L1CSR0,r0
128 isync
129
130 /* disable d-cache */
131 li r0,0x0
132 mtspr L1CSR0,r0
133 isync
134
135 /* invalidate i-cache */
136 mfspr r0,L1CSR1
137 ori r0,r0,0x0002
138 mtspr L1CSR1,r0
139 isync
140
141 /* disable i-cache */
142 li r0,0x0
143 mtspr L1CSR1,r0
144 isync
145
146 /* clear registers */
147 sync
148 li r0,0
149 mtspr SRR0,r0
150 mtspr SRR1,r0
151 mtspr CSRR0,r0
152 mtspr CSRR1,r0
153 mtspr MCSRR0,r0
154 mtspr MCSRR1,r0
155
156 mtspr ESR,r0
157 mtspr MCSR,r0
158 mtspr DEAR,r0
159
160 mtspr DBCR0,r0
161 isync
162 mtspr DBCR1,r0
163 isync
164 mtspr DBCR2,r0
165 isync
166 mtspr IAC1,r0
167 mtspr IAC2,r0
168 mtspr DAC1,r0
169 mtspr DAC2,r0
170
171 mfspr r1,DBSR
172 mtspr DBSR,r1 /* Clear all valid bits */
173
174 isync
175 mtspr PID0,r0
176 isync
177 mtspr PID1,r0
178 isync
179 mtspr PID2,r0
180 isync
181
182 mtspr TCR,r0
183
184 mtspr BUCSR,r0 /* disable branch prediction */
185 isync
186
187 mtspr HID0,r0
188 isync
189 mtspr HID1,r0
190 isync
191
192 mtspr MAS4,r0
193 isync
194 mtspr MAS6,r0
195 isync
196
197 /* Setup interrupt vectors */
wdenk97d80fc2004-06-09 00:34:46 +0000198 lis r1,0xfff8
199 mtspr IVPR, r1
wdenk42d1f032003-10-15 23:53:47 +0000200
201 li r1,0x0100
202 mtspr IVOR0,r1 /* 0: Critical input */
203 li r1,0x0200
204 mtspr IVOR1,r1 /* 1: Machine check */
205 li r1,0x0300
206 mtspr IVOR2,r1 /* 2: Data storage */
207 li r1,0x0400
208 mtspr IVOR3,r1 /* 3: Instruction storage */
209 li r1,0x0500
210 mtspr IVOR4,r1 /* 4: External interrupt */
211 li r1,0x0600
212 mtspr IVOR5,r1 /* 5: Alignment */
213 li r1,0x0700
214 mtspr IVOR6,r1 /* 6: Program check */
215 li r1,0x0800
216 mtspr IVOR7,r1 /* 7: floating point unavailable */
217 li r1,0x0c00
218 mtspr IVOR8,r1 /* 8: System call */
219 /* 9: Auxiliary processor unavailable(unsupported) */
220 li r1,0x1000
221 mtspr IVOR10,r1 /* 10: Decrementer */
222 li r1,0x1400
223 mtspr IVOR13,r1 /* 13: Data TLB error */
224 li r1,0x1300
225 mtspr IVOR14,r1 /* 14: Instruction TLB error */
226 li r1,0x2000
227 mtspr IVOR15,r1 /* 15: Debug */
228
wdenk97d80fc2004-06-09 00:34:46 +0000229 /*
230 * Invalidate MMU L1/L2
231 *
232 * Note: There is a fixup earlier for Errata CPU4 on
233 * Rev 1 parts that must precede this MMU invalidation.
wdenk42d1f032003-10-15 23:53:47 +0000234 */
wdenk42d1f032003-10-15 23:53:47 +0000235 li r2, 0x001e
236 mtspr MMUCSR0, r2
237 isync
wdenk42d1f032003-10-15 23:53:47 +0000238
239 /* After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
240 * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
241 * region before we can access any CCSR registers such as L2
242 * registers, Local Access Registers,etc. We will also re-allocate
243 * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
244 *
245 * Please refer to board-specif directory for TLB1 entry configuration.
246 * (e.g. board/<yourboard>/init.S)
247 *
248 */
249 bl tlb1_entry
250 mr r5,r0
251 li r1,0x000f /* max 16 TLB1 entries */
252 mtctr r1
253 lwzu r4,0(r5) /* how many TLB1 entries we actually use */
254
2550: cmpwi r4,0
256 beq 1f
257 lwzu r0,4(r5)
258 lwzu r1,4(r5)
259 lwzu r2,4(r5)
260 lwzu r3,4(r5)
261 mtspr MAS0,r0
262 mtspr MAS1,r1
263 mtspr MAS2,r2
264 mtspr MAS3,r3
265 isync
266 msync
267 tlbwe
268 isync
269 addi r4,r4,-1
270 bdnz 0b
271
2721:
273#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
274 /* Special sequence needed to update CCSRBAR itself */
275 lis r4, CFG_CCSRBAR_DEFAULT@h
276 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
277
278 lis r5, CFG_CCSRBAR@h
279 ori r5, r5, CFG_CCSRBAR@l
280 srwi r6,r5,12
281 stw r6, 0(r4)
282 isync
283
284 lis r5, 0xffff
285 ori r5,r5,0xf000
286 lwz r5, 0(r5)
287 isync
288
289 lis r3, CFG_CCSRBAR@h
290 lwz r5, CFG_CCSRBAR@l(r3)
291 isync
292#endif
293
294 /* invalidate all TLB0 entries */
295 li r3,4
296 li r4,0
297 tlbivax r4,r3
wdenk97d80fc2004-06-09 00:34:46 +0000298 /*
299 * To avoid REV1 Errata CPU6 issues, make sure
300 * the instruction following tlbivax is not a store.
301 */
302
wdenk42d1f032003-10-15 23:53:47 +0000303
304 /* set up local access windows, defined at board/<boardname>/init.S */
305 lis r7,CFG_CCSRBAR@h
306 ori r7,r7,CFG_CCSRBAR@l
307
308 bl law_entry
309 mr r6,r0
310#if defined(CONFIG_RAM_AS_FLASH)
311 li r1,0x0006
312#else
313 li r1,0x0007 /*we have 8 LAWs, but reseve one for boot-over-rio-or-pci */
314#endif
315 mtctr r1
316 lwzu r5,0(r6) /* how many windows we actually use */
317
318#if defined(CONFIG_RAM_AS_FLASH)
319 li r2,0x0c48
320 li r1,0x0c50
321#else
322 li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
323 li r1,0x0c30
324#endif
325
3260: cmpwi r5,0
327 beq 1f
328 lwzu r4,4(r6)
329 lwzu r3,4(r6)
330 stwx r4,r7,r2
331 stwx r3,r7,r1
332 addi r5,r5,-1
333 addi r2,r2,0x0020
334 addi r1,r1,0x0020
335 bdnz 0b
336
337 /* Jump out the last 4K page and continue to 'normal' start */
3381: bl 3f
339 b _start
340
3413: li r0,0
342 mtspr SRR1,r0 /* Keep things disabled for now */
343 mflr r1
344 mtspr SRR0,r1
345 rfi
346
347/*
348 * r3 - 1st arg to board_init(): IMMP pointer
349 * r4 - 2nd arg to board_init(): boot flag
350 */
351 .text
352 .long 0x27051956 /* U-BOOT Magic Number */
353 .globl version_string
354version_string:
355 .ascii U_BOOT_VERSION
356 .ascii " (", __DATE__, " - ", __TIME__, ")"
357 .ascii CONFIG_IDENT_STRING, "\0"
358
359 . = EXC_OFF_SYS_RESET
360 .globl _start
361_start:
362 /* Clear and set up some registers. */
363 li r0,0x0000
364 lis r1,0xffff
365 mtspr DEC,r0 /* prevent dec exceptions */
366 mttbl r0 /* prevent fit & wdt exceptions */
367 mttbu r0
368 mtspr TSR,r1 /* clear all timer exception status */
369 mtspr TCR,r0 /* disable all */
370 mtspr ESR,r0 /* clear exception syndrome register */
371 mtspr MCSR,r0 /* machine check syndrome register */
372 mtxer r0 /* clear integer exception register */
373 lis r1,0x0002 /* set CE bit (Critical Exceptions) */
374 ori r1,r1,0x1200 /* set ME/DE bit */
375 mtmsr r1 /* change MSR */
376 isync
377
378 /* Enable Time Base and Select Time Base Clock */
379 li r0,0x4000 /* time base is processor clock */
380 mtspr HID0,r0
381 isync
382
383#if defined(CONFIG_ADDR_STREAMING)
wdenka57a4962003-10-26 22:52:58 +0000384 li r0,0x3000
385#else
386 li r0,0x1000
387#endif
wdenk42d1f032003-10-15 23:53:47 +0000388 mtspr HID1,r0
389 isync
wdenk42d1f032003-10-15 23:53:47 +0000390
391 /* Enable Branch Prediction */
392#if defined(CONFIG_BTB)
393 li r0,0x201 /* BBFI = 1, BPEN = 1 */
394 mtspr BUCSR,r0
395 isync
396#endif
397
398#if defined(CFG_INIT_DBCR)
399 lis r1,0xffff
400 ori r1,r1,0xffff
401 mtspr dbsr,r1 /* Clear all status bits */
402 lis r0,CFG_INIT_DBCR@h /* DBCR0[IDM] must be set */
403 ori r0,r0,CFG_INIT_DBCR@l
404 mtspr dbcr0,r0
405 isync
406#endif
407
408/* L1 DCache is used for initial RAM */
409 mfspr r2, L1CSR0
410 ori r2, r2, 0x0003
411 oris r2, r2, 0x0001
412 msync
413 isync
414 mtspr L1CSR0, r2 /* enable/invalidate L1 Dcache */
415 isync
416
417 /* Allocate Initial RAM in data cache.
418 */
419 lis r3, CFG_INIT_RAM_ADDR@h
420 ori r3, r3, CFG_INIT_RAM_ADDR@l
421 li r2, 512 /* 512*32=16K */
422 mtctr r2
423 li r0, 0
4241:
425 dcbz r0, r3
426 dcbtls 0,r0, r3
427 addi r3, r3, 32
428 bdnz 1b
429
430#ifndef CFG_RAMBOOT
431 /* Calculate absolute address in FLASH and jump there */
432 /*--------------------------------------------------------------*/
433 lis r3, CFG_MONITOR_BASE@h
434 ori r3, r3, CFG_MONITOR_BASE@l
435 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
436 mtlr r3
437 blr
438
439in_flash:
440#endif /* CFG_RAMBOOT */
441
442 /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
443 lis r1,CFG_INIT_RAM_ADDR@h
444 ori r1,r1,CFG_INIT_SP_OFFSET@l
445
446 li r0,0
447 stwu r0,-4(r1)
448 stwu r0,-4(r1) /* Terminate call chain */
449
450 stwu r1,-8(r1) /* Save back chain and move SP */
451 lis r0,RESET_VECTOR@h /* Address of reset vector */
452 ori r0,r0, RESET_VECTOR@l
453 stwu r1,-8(r1) /* Save back chain and move SP */
454 stw r0,+12(r1) /* Save return addr (underflow vect) */
455
456 GET_GOT
457 bl cpu_init_f
458 bl icache_enable
459 bl board_init_f
460 sync
461
462
463/* --FIXME-- machine check with MCSRRn and rfmci */
464
465 .globl _start_of_vectors
466_start_of_vectors:
467#if 0
468/* Critical input. */
469 CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
470#endif
471/* Machine check --FIXME-- Should be MACH_EXCEPTION */
472 CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
473
474/* Data Storage exception. */
475 STD_EXCEPTION(0x0300, DataStorage, UnknownException)
476
477/* Instruction Storage exception. */
478 STD_EXCEPTION(0x0400, InstStorage, UnknownException)
479
480/* External Interrupt exception. */
481 STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
482
483/* Alignment exception. */
484 . = 0x0600
485Alignment:
486 EXCEPTION_PROLOG
487 mfspr r4,DAR
488 stw r4,_DAR(r21)
489 mfspr r5,DSISR
490 stw r5,_DSISR(r21)
491 addi r3,r1,STACK_FRAME_OVERHEAD
492 li r20,MSR_KERNEL
493 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
494 lwz r6,GOT(transfer_to_handler)
495 mtlr r6
496 blrl
497.L_Alignment:
498 .long AlignmentException - _start + EXC_OFF_SYS_RESET
499 .long int_return - _start + EXC_OFF_SYS_RESET
500
501/* Program check exception */
502 . = 0x0700
503ProgramCheck:
504 EXCEPTION_PROLOG
505 addi r3,r1,STACK_FRAME_OVERHEAD
506 li r20,MSR_KERNEL
507 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
508 lwz r6,GOT(transfer_to_handler)
509 mtlr r6
510 blrl
511.L_ProgramCheck:
512 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
513 .long int_return - _start + EXC_OFF_SYS_RESET
514
515 /* No FPU on MPC85xx. This exception is not supposed to happen.
516 */
517 STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
518 STD_EXCEPTION(0x0900, Decrementer, timer_interrupt)
519 STD_EXCEPTION(0x0a00, Trap_0a, UnknownException)
520 STD_EXCEPTION(0x0b00, Trap_0b, UnknownException)
521
522 . = 0x0c00
523/*
524 * r0 - SYSCALL number
525 * r3-... arguments
526 */
527SystemCall:
528 addis r11,r0,0 /* get functions table addr */
529 ori r11,r11,0 /* Note: this code is patched in trap_init */
530 addis r12,r0,0 /* get number of functions */
531 ori r12,r12,0
532
533 cmplw 0, r0, r12
534 bge 1f
535
536 rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
537 add r11,r11,r0
538 lwz r11,0(r11)
539
540 li r20,0xd00-4 /* Get stack pointer */
541 lwz r12,0(r20)
542 subi r12,r12,12 /* Adjust stack pointer */
543 li r0,0xc00+_end_back-SystemCall
544 cmplw 0, r0, r12 /* Check stack overflow */
545 bgt 1f
546 stw r12,0(r20)
547
548 mflr r0
549 stw r0,0(r12)
550 mfspr r0,SRR0
551 stw r0,4(r12)
552 mfspr r0,SRR1
553 stw r0,8(r12)
554
555 li r12,0xc00+_back-SystemCall
556 mtlr r12
557 mtspr SRR0,r11
558
5591: SYNC
560 rfi
561_back:
562
563 mfmsr r11 /* Disable interrupts */
564 li r12,0
565 ori r12,r12,MSR_EE
566 andc r11,r11,r12
567 SYNC /* Some chip revs need this... */
568 mtmsr r11
569 SYNC
570
571 li r12,0xd00-4 /* restore regs */
572 lwz r12,0(r12)
573
574 lwz r11,0(r12)
575 mtlr r11
576 lwz r11,4(r12)
577 mtspr SRR0,r11
578 lwz r11,8(r12)
579 mtspr SRR1,r11
580
581 addi r12,r12,12 /* Adjust stack pointer */
582 li r20,0xd00-4
583 stw r12,0(r20)
584
585 SYNC
586 rfi
587_end_back:
588
589 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
590
591 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
592 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
593
594 STD_EXCEPTION(0x1000, PIT, PITException)
595
596 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
597 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
598 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
599 STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
600
601 STD_EXCEPTION(0x1500, Reserved5, UnknownException)
602 STD_EXCEPTION(0x1600, Reserved6, UnknownException)
603 STD_EXCEPTION(0x1700, Reserved7, UnknownException)
604 STD_EXCEPTION(0x1800, Reserved8, UnknownException)
605 STD_EXCEPTION(0x1900, Reserved9, UnknownException)
606 STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
607 STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
608
609 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
610 STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
611 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
612 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
613
614 CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
615
616 .globl _end_of_vectors
617_end_of_vectors:
618
619
620 . = 0x2100
621
622/*
623 * This code finishes saving the registers to the exception frame
624 * and jumps to the appropriate handler for the exception.
625 * Register r21 is pointer into trap frame, r1 has new stack pointer.
626 */
627 .globl transfer_to_handler
628transfer_to_handler:
629 stw r22,_NIP(r21)
630 lis r22,MSR_POW@h
631 andc r23,r23,r22
632 stw r23,_MSR(r21)
633 SAVE_GPR(7, r21)
634 SAVE_4GPRS(8, r21)
635 SAVE_8GPRS(12, r21)
636 SAVE_8GPRS(24, r21)
637
638 mflr r23
639 andi. r24,r23,0x3f00 /* get vector offset */
640 stw r24,TRAP(r21)
641 li r22,0
642 stw r22,RESULT(r21)
643 mtspr SPRG2,r22 /* r1 is now kernel sp */
644
645 lwz r24,0(r23) /* virtual address of handler */
646 lwz r23,4(r23) /* where to go when done */
647 mtspr SRR0,r24
648 mtspr SRR1,r20
649 mtlr r23
650 SYNC
651 rfi /* jump to handler, enable MMU */
652
653int_return:
654 mfmsr r28 /* Disable interrupts */
655 li r4,0
656 ori r4,r4,MSR_EE
657 andc r28,r28,r4
658 SYNC /* Some chip revs need this... */
659 mtmsr r28
660 SYNC
661 lwz r2,_CTR(r1)
662 lwz r0,_LINK(r1)
663 mtctr r2
664 mtlr r0
665 lwz r2,_XER(r1)
666 lwz r0,_CCR(r1)
667 mtspr XER,r2
668 mtcrf 0xFF,r0
669 REST_10GPRS(3, r1)
670 REST_10GPRS(13, r1)
671 REST_8GPRS(23, r1)
672 REST_GPR(31, r1)
673 lwz r2,_NIP(r1) /* Restore environment */
674 lwz r0,_MSR(r1)
675 mtspr SRR0,r2
676 mtspr SRR1,r0
677 lwz r0,GPR0(r1)
678 lwz r2,GPR2(r1)
679 lwz r1,GPR1(r1)
680 SYNC
681 rfi
682
683crit_return:
684 mfmsr r28 /* Disable interrupts */
685 li r4,0
686 ori r4,r4,MSR_EE
687 andc r28,r28,r4
688 SYNC /* Some chip revs need this... */
689 mtmsr r28
690 SYNC
691 lwz r2,_CTR(r1)
692 lwz r0,_LINK(r1)
693 mtctr r2
694 mtlr r0
695 lwz r2,_XER(r1)
696 lwz r0,_CCR(r1)
697 mtspr XER,r2
698 mtcrf 0xFF,r0
699 REST_10GPRS(3, r1)
700 REST_10GPRS(13, r1)
701 REST_8GPRS(23, r1)
702 REST_GPR(31, r1)
703 lwz r2,_NIP(r1) /* Restore environment */
704 lwz r0,_MSR(r1)
705 mtspr 990,r2 /* SRR2 */
706 mtspr 991,r0 /* SRR3 */
707 lwz r0,GPR0(r1)
708 lwz r2,GPR2(r1)
709 lwz r1,GPR1(r1)
710 SYNC
711 rfci
712
713/* Cache functions.
714*/
715invalidate_icache:
716 mfspr r0,L1CSR1
717 ori r0,r0,0x0002
718 mtspr L1CSR1,r0
719 isync
720 blr /* entire I cache */
721
722invalidate_dcache:
723 mfspr r0,L1CSR0
724 ori r0,r0,0x0002
725 msync
726 isync
727 mtspr L1CSR0,r0
728 isync
729 blr
730
731 .globl icache_enable
732icache_enable:
733 mflr r8
734 bl invalidate_icache
735 mtlr r8
736 isync
737 mfspr r4,L1CSR1
738 ori r4,r4,0x0001
739 oris r4,r4,0x0001
740 mtspr L1CSR1,r4
741 isync
742 blr
743
744 .globl icache_disable
745icache_disable:
746 mfspr r0,L1CSR1
747 lis r1,0xfffffffe@h
748 ori r1,r1,0xfffffffe@l
749 and r0,r0,r1
750 mtspr L1CSR1,r0
751 isync
752 blr
753
754 .globl icache_status
755icache_status:
756 mfspr r3,L1CSR1
757 srwi r3, r3, 31 /* >>31 => select bit 0 */
758 blr
759
760 .globl dcache_enable
761dcache_enable:
762 mflr r8
763 bl invalidate_dcache
764 mtlr r8
765 isync
766 mfspr r0,L1CSR0
767 ori r0,r0,0x0001
768 oris r0,r0,0x0001
769 msync
770 isync
771 mtspr L1CSR0,r0
772 isync
773 blr
774
775 .globl dcache_disable
776dcache_disable:
777 mfspr r0,L1CSR0
778 lis r1,0xfffffffe@h
779 ori r1,r1,0xfffffffe@l
780 and r0,r0,r1
781 msync
782 isync
783 mtspr L1CSR0,r0
784 isync
785 blr
786
787 .globl dcache_status
788dcache_status:
789 mfspr r3,L1CSR0
790 srwi r3, r3, 31 /* >>31 => select bit 0 */
791 blr
792
793 .globl get_pir
794get_pir:
795 mfspr r3, PIR
796 blr
797
798 .globl get_pvr
799get_pvr:
800 mfspr r3, PVR
801 blr
802
wdenk97d80fc2004-06-09 00:34:46 +0000803 .globl get_svr
804get_svr:
805 mfspr r3, SVR
806 blr
807
wdenk42d1f032003-10-15 23:53:47 +0000808 .globl wr_tcr
809wr_tcr:
810 mtspr TCR, r3
811 blr
812
813/*------------------------------------------------------------------------------- */
814/* Function: in8 */
815/* Description: Input 8 bits */
816/*------------------------------------------------------------------------------- */
817 .globl in8
818in8:
819 lbz r3,0x0000(r3)
820 blr
821
822/*------------------------------------------------------------------------------- */
823/* Function: out8 */
824/* Description: Output 8 bits */
825/*------------------------------------------------------------------------------- */
826 .globl out8
827out8:
828 stb r4,0x0000(r3)
829 blr
830
831/*------------------------------------------------------------------------------- */
832/* Function: out16 */
833/* Description: Output 16 bits */
834/*------------------------------------------------------------------------------- */
835 .globl out16
836out16:
837 sth r4,0x0000(r3)
838 blr
839
840/*------------------------------------------------------------------------------- */
841/* Function: out16r */
842/* Description: Byte reverse and output 16 bits */
843/*------------------------------------------------------------------------------- */
844 .globl out16r
845out16r:
846 sthbrx r4,r0,r3
847 blr
848
849/*------------------------------------------------------------------------------- */
850/* Function: out32 */
851/* Description: Output 32 bits */
852/*------------------------------------------------------------------------------- */
853 .globl out32
854out32:
855 stw r4,0x0000(r3)
856 blr
857
858/*------------------------------------------------------------------------------- */
859/* Function: out32r */
860/* Description: Byte reverse and output 32 bits */
861/*------------------------------------------------------------------------------- */
862 .globl out32r
863out32r:
864 stwbrx r4,r0,r3
865 blr
866
867/*------------------------------------------------------------------------------- */
868/* Function: in16 */
869/* Description: Input 16 bits */
870/*------------------------------------------------------------------------------- */
871 .globl in16
872in16:
873 lhz r3,0x0000(r3)
874 blr
875
876/*------------------------------------------------------------------------------- */
877/* Function: in16r */
878/* Description: Input 16 bits and byte reverse */
879/*------------------------------------------------------------------------------- */
880 .globl in16r
881in16r:
882 lhbrx r3,r0,r3
883 blr
884
885/*------------------------------------------------------------------------------- */
886/* Function: in32 */
887/* Description: Input 32 bits */
888/*------------------------------------------------------------------------------- */
889 .globl in32
890in32:
891 lwz 3,0x0000(3)
892 blr
893
894/*------------------------------------------------------------------------------- */
895/* Function: in32r */
896/* Description: Input 32 bits and byte reverse */
897/*------------------------------------------------------------------------------- */
898 .globl in32r
899in32r:
900 lwbrx r3,r0,r3
901 blr
902
903/*------------------------------------------------------------------------------- */
904/* Function: ppcDcbf */
905/* Description: Data Cache block flush */
906/* Input: r3 = effective address */
907/* Output: none. */
908/*------------------------------------------------------------------------------- */
909 .globl ppcDcbf
910ppcDcbf:
911 dcbf r0,r3
912 blr
913
914/*------------------------------------------------------------------------------- */
915/* Function: ppcDcbi */
916/* Description: Data Cache block Invalidate */
917/* Input: r3 = effective address */
918/* Output: none. */
919/*------------------------------------------------------------------------------- */
920 .globl ppcDcbi
921ppcDcbi:
922 dcbi r0,r3
923 blr
924
925/*------------------------------------------------------------------------------- */
926/* Function: ppcSync */
927/* Description: Processor Synchronize */
928/* Input: none. */
929/* Output: none. */
930/*------------------------------------------------------------------------------- */
931 .globl ppcSync
932ppcSync:
933 sync
934 blr
935
936/*------------------------------------------------------------------------------*/
937
938/*
939 * void relocate_code (addr_sp, gd, addr_moni)
940 *
941 * This "function" does not return, instead it continues in RAM
942 * after relocating the monitor code.
943 *
944 * r3 = dest
945 * r4 = src
946 * r5 = length in bytes
947 * r6 = cachelinesize
948 */
949 .globl relocate_code
950relocate_code:
951 mr r1, r3 /* Set new stack pointer */
952 mr r9, r4 /* Save copy of Init Data pointer */
953 mr r10, r5 /* Save copy of Destination Address */
954
955 mr r3, r5 /* Destination Address */
956 lis r4, CFG_MONITOR_BASE@h /* Source Address */
957 ori r4, r4, CFG_MONITOR_BASE@l
958 lwz r5,GOT(__init_end)
959 sub r5,r5,r4
960 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
961
962 /*
963 * Fix GOT pointer:
964 *
965 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
966 *
967 * Offset:
968 */
969 sub r15, r10, r4
970
971 /* First our own GOT */
972 add r14, r14, r15
973 /* the the one used by the C code */
974 add r30, r30, r15
975
976 /*
977 * Now relocate code
978 */
979
980 cmplw cr1,r3,r4
981 addi r0,r5,3
982 srwi. r0,r0,2
983 beq cr1,4f /* In place copy is not necessary */
984 beq 7f /* Protect against 0 count */
985 mtctr r0
986 bge cr1,2f
987
988 la r8,-4(r4)
989 la r7,-4(r3)
9901: lwzu r0,4(r8)
991 stwu r0,4(r7)
992 bdnz 1b
993 b 4f
994
9952: slwi r0,r0,2
996 add r8,r4,r0
997 add r7,r3,r0
9983: lwzu r0,-4(r8)
999 stwu r0,-4(r7)
1000 bdnz 3b
1001
1002/*
1003 * Now flush the cache: note that we must start from a cache aligned
1004 * address. Otherwise we might miss one cache line.
1005 */
10064: cmpwi r6,0
1007 add r5,r3,r5
1008 beq 7f /* Always flush prefetch queue in any case */
1009 subi r0,r6,1
1010 andc r3,r3,r0
1011 mr r4,r3
10125: dcbst 0,r4
1013 add r4,r4,r6
1014 cmplw r4,r5
1015 blt 5b
1016 sync /* Wait for all dcbst to complete on bus */
1017 mr r4,r3
10186: icbi 0,r4
1019 add r4,r4,r6
1020 cmplw r4,r5
1021 blt 6b
10227: sync /* Wait for all icbi to complete on bus */
1023 isync
1024
1025/*
1026 * We are done. Do not return, instead branch to second part of board
1027 * initialization, now running from RAM.
1028 */
1029
1030 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1031 mtlr r0
1032 blr /* NEVER RETURNS! */
1033
1034in_ram:
1035
1036 /*
1037 * Relocation Function, r14 point to got2+0x8000
1038 *
1039 * Adjust got2 pointers, no need to check for 0, this code
1040 * already puts a few entries in the table.
1041 */
1042 li r0,__got2_entries@sectoff@l
1043 la r3,GOT(_GOT2_TABLE_)
1044 lwz r11,GOT(_GOT2_TABLE_)
1045 mtctr r0
1046 sub r11,r3,r11
1047 addi r3,r3,-4
10481: lwzu r0,4(r3)
1049 add r0,r0,r11
1050 stw r0,0(r3)
1051 bdnz 1b
1052
1053 /*
1054 * Now adjust the fixups and the pointers to the fixups
1055 * in case we need to move ourselves again.
1056 */
10572: li r0,__fixup_entries@sectoff@l
1058 lwz r3,GOT(_FIXUP_TABLE_)
1059 cmpwi r0,0
1060 mtctr r0
1061 addi r3,r3,-4
1062 beq 4f
10633: lwzu r4,4(r3)
1064 lwzux r0,r4,r11
1065 add r0,r0,r11
1066 stw r10,0(r3)
1067 stw r0,0(r4)
1068 bdnz 3b
10694:
1070clear_bss:
1071 /*
1072 * Now clear BSS segment
1073 */
1074 lwz r3,GOT(__bss_start)
1075 lwz r4,GOT(_end)
1076
1077 cmplw 0, r3, r4
1078 beq 6f
1079
1080 li r0, 0
10815:
1082 stw r0, 0(r3)
1083 addi r3, r3, 4
1084 cmplw 0, r3, r4
1085 bne 5b
10866:
1087
1088 mr r3, r9 /* Init Data pointer */
1089 mr r4, r10 /* Destination Address */
1090 bl board_init_r
1091
1092 /*
1093 * Copy exception vector code to low memory
1094 *
1095 * r3: dest_addr
1096 * r7: source address, r8: end address, r9: target address
1097 */
1098 .globl trap_init
1099trap_init:
1100 lwz r7, GOT(_start)
1101 lwz r8, GOT(_end_of_vectors)
1102
1103 li r9, 0x100 /* reset vector always at 0x100 */
1104
1105 cmplw 0, r7, r8
1106 bgelr /* return if r7>=r8 - just in case */
1107
1108 mflr r4 /* save link register */
11091:
1110 lwz r0, 0(r7)
1111 stw r0, 0(r9)
1112 addi r7, r7, 4
1113 addi r9, r9, 4
1114 cmplw 0, r7, r8
1115 bne 1b
1116
1117 /*
1118 * relocate `hdlr' and `int_return' entries
1119 */
1120 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1121 li r8, Alignment - _start + EXC_OFF_SYS_RESET
11222:
1123 bl trap_reloc
1124 addi r7, r7, 0x100 /* next exception vector */
1125 cmplw 0, r7, r8
1126 blt 2b
1127
1128 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1129 bl trap_reloc
1130
1131 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1132 bl trap_reloc
1133
1134 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1135 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
11363:
1137 bl trap_reloc
1138 addi r7, r7, 0x100 /* next exception vector */
1139 cmplw 0, r7, r8
1140 blt 3b
1141
1142 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1143 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
11444:
1145 bl trap_reloc
1146 addi r7, r7, 0x100 /* next exception vector */
1147 cmplw 0, r7, r8
1148 blt 4b
1149
1150 mtlr r4 /* restore link register */
1151 blr
1152
1153 /*
1154 * Function: relocate entries for one exception vector
1155 */
1156trap_reloc:
1157 lwz r0, 0(r7) /* hdlr ... */
1158 add r0, r0, r3 /* ... += dest_addr */
1159 stw r0, 0(r7)
1160
1161 lwz r0, 4(r7) /* int_return ... */
1162 add r0, r0, r3 /* ... += dest_addr */
1163 stw r0, 4(r7)
1164
1165 blr
1166
1167#ifdef CFG_INIT_RAM_LOCK
1168.globl unlock_ram_in_cache
1169unlock_ram_in_cache:
1170 /* invalidate the INIT_RAM section */
1171 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1172 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1173 li r2,512
1174 mtctr r2
11751: icbi r0, r3
1176 dcbi r0, r3
1177 addi r3, r3, 32
1178 bdnz 1b
1179 sync /* Wait for all icbi to complete on bus */
1180 isync
1181 blr
1182#endif