blob: 9207396cdfc752c14a723f6fb1e0f2e7b0948e4f [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
wdenk42d1f032003-10-15 23:53:47 +0000133
134 /* invalidate i-cache */
135 mfspr r0,L1CSR1
136 ori r0,r0,0x0002
137 mtspr L1CSR1,r0
138 isync
139
140 /* disable i-cache */
141 li r0,0x0
142 mtspr L1CSR1,r0
143 isync
144
145 /* clear registers */
wdenk42d1f032003-10-15 23:53:47 +0000146 li r0,0
147 mtspr SRR0,r0
148 mtspr SRR1,r0
149 mtspr CSRR0,r0
150 mtspr CSRR1,r0
151 mtspr MCSRR0,r0
152 mtspr MCSRR1,r0
153
154 mtspr ESR,r0
155 mtspr MCSR,r0
156 mtspr DEAR,r0
157
158 mtspr DBCR0,r0
wdenk42d1f032003-10-15 23:53:47 +0000159 mtspr DBCR1,r0
wdenk42d1f032003-10-15 23:53:47 +0000160 mtspr DBCR2,r0
wdenk42d1f032003-10-15 23:53:47 +0000161 mtspr IAC1,r0
162 mtspr IAC2,r0
163 mtspr DAC1,r0
164 mtspr DAC2,r0
165
166 mfspr r1,DBSR
167 mtspr DBSR,r1 /* Clear all valid bits */
168
wdenk42d1f032003-10-15 23:53:47 +0000169 mtspr PID0,r0
wdenk42d1f032003-10-15 23:53:47 +0000170 mtspr PID1,r0
wdenk42d1f032003-10-15 23:53:47 +0000171 mtspr PID2,r0
wdenk42d1f032003-10-15 23:53:47 +0000172 mtspr TCR,r0
173
174 mtspr BUCSR,r0 /* disable branch prediction */
wdenk42d1f032003-10-15 23:53:47 +0000175 mtspr MAS4,r0
wdenk42d1f032003-10-15 23:53:47 +0000176 mtspr MAS6,r0
177 isync
178
179 /* Setup interrupt vectors */
wdenk97d80fc2004-06-09 00:34:46 +0000180 lis r1,0xfff8
181 mtspr IVPR, r1
wdenk42d1f032003-10-15 23:53:47 +0000182
183 li r1,0x0100
184 mtspr IVOR0,r1 /* 0: Critical input */
185 li r1,0x0200
186 mtspr IVOR1,r1 /* 1: Machine check */
187 li r1,0x0300
188 mtspr IVOR2,r1 /* 2: Data storage */
189 li r1,0x0400
190 mtspr IVOR3,r1 /* 3: Instruction storage */
191 li r1,0x0500
192 mtspr IVOR4,r1 /* 4: External interrupt */
193 li r1,0x0600
194 mtspr IVOR5,r1 /* 5: Alignment */
195 li r1,0x0700
196 mtspr IVOR6,r1 /* 6: Program check */
197 li r1,0x0800
198 mtspr IVOR7,r1 /* 7: floating point unavailable */
199 li r1,0x0c00
200 mtspr IVOR8,r1 /* 8: System call */
201 /* 9: Auxiliary processor unavailable(unsupported) */
202 li r1,0x1000
203 mtspr IVOR10,r1 /* 10: Decrementer */
204 li r1,0x1400
205 mtspr IVOR13,r1 /* 13: Data TLB error */
206 li r1,0x1300
207 mtspr IVOR14,r1 /* 14: Instruction TLB error */
208 li r1,0x2000
209 mtspr IVOR15,r1 /* 15: Debug */
210
wdenk97d80fc2004-06-09 00:34:46 +0000211 /*
212 * Invalidate MMU L1/L2
213 *
214 * Note: There is a fixup earlier for Errata CPU4 on
215 * Rev 1 parts that must precede this MMU invalidation.
wdenk42d1f032003-10-15 23:53:47 +0000216 */
wdenk42d1f032003-10-15 23:53:47 +0000217 li r2, 0x001e
218 mtspr MMUCSR0, r2
219 isync
wdenk42d1f032003-10-15 23:53:47 +0000220
wdenk9aea9532004-08-01 23:02:45 +0000221 /*
222 * Invalidate all TLB0 entries.
223 */
224 li r3,4
225 li r4,0
226 tlbivax r4,r3
227 /*
228 * To avoid REV1 Errata CPU6 issues, make sure
229 * the instruction following tlbivax is not a store.
230 */
231
232 /*
233 * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
wdenk42d1f032003-10-15 23:53:47 +0000234 * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
235 * region before we can access any CCSR registers such as L2
236 * registers, Local Access Registers,etc. We will also re-allocate
237 * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
238 *
239 * Please refer to board-specif directory for TLB1 entry configuration.
240 * (e.g. board/<yourboard>/init.S)
241 *
242 */
243 bl tlb1_entry
244 mr r5,r0
wdenk9aea9532004-08-01 23:02:45 +0000245 li r1,0x0020 /* max 16 TLB1 plus some TLB0 entries */
wdenk42d1f032003-10-15 23:53:47 +0000246 mtctr r1
247 lwzu r4,0(r5) /* how many TLB1 entries we actually use */
248
2490: cmpwi r4,0
250 beq 1f
251 lwzu r0,4(r5)
252 lwzu r1,4(r5)
253 lwzu r2,4(r5)
254 lwzu r3,4(r5)
255 mtspr MAS0,r0
256 mtspr MAS1,r1
257 mtspr MAS2,r2
258 mtspr MAS3,r3
259 isync
260 msync
261 tlbwe
262 isync
263 addi r4,r4,-1
264 bdnz 0b
265
2661:
267#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
268 /* Special sequence needed to update CCSRBAR itself */
269 lis r4, CFG_CCSRBAR_DEFAULT@h
270 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
271
272 lis r5, CFG_CCSRBAR@h
273 ori r5, r5, CFG_CCSRBAR@l
274 srwi r6,r5,12
275 stw r6, 0(r4)
276 isync
277
278 lis r5, 0xffff
279 ori r5,r5,0xf000
280 lwz r5, 0(r5)
281 isync
282
283 lis r3, CFG_CCSRBAR@h
284 lwz r5, CFG_CCSRBAR@l(r3)
285 isync
286#endif
287
wdenk42d1f032003-10-15 23:53:47 +0000288
289 /* set up local access windows, defined at board/<boardname>/init.S */
290 lis r7,CFG_CCSRBAR@h
291 ori r7,r7,CFG_CCSRBAR@l
292
293 bl law_entry
294 mr r6,r0
wdenk9aea9532004-08-01 23:02:45 +0000295 li r1,0x0007 /* 8 LAWs, but reserve one for boot-over-rio-or-pci */
wdenk42d1f032003-10-15 23:53:47 +0000296 mtctr r1
297 lwzu r5,0(r6) /* how many windows we actually use */
298
wdenk42d1f032003-10-15 23:53:47 +0000299 li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
300 li r1,0x0c30
wdenk42d1f032003-10-15 23:53:47 +0000301
3020: cmpwi r5,0
303 beq 1f
304 lwzu r4,4(r6)
305 lwzu r3,4(r6)
306 stwx r4,r7,r2
307 stwx r3,r7,r1
308 addi r5,r5,-1
309 addi r2,r2,0x0020
310 addi r1,r1,0x0020
311 bdnz 0b
312
313 /* Jump out the last 4K page and continue to 'normal' start */
3141: bl 3f
315 b _start
316
3173: li r0,0
318 mtspr SRR1,r0 /* Keep things disabled for now */
319 mflr r1
320 mtspr SRR0,r1
321 rfi
322
323/*
324 * r3 - 1st arg to board_init(): IMMP pointer
325 * r4 - 2nd arg to board_init(): boot flag
326 */
327 .text
328 .long 0x27051956 /* U-BOOT Magic Number */
329 .globl version_string
330version_string:
331 .ascii U_BOOT_VERSION
332 .ascii " (", __DATE__, " - ", __TIME__, ")"
333 .ascii CONFIG_IDENT_STRING, "\0"
334
335 . = EXC_OFF_SYS_RESET
336 .globl _start
337_start:
338 /* Clear and set up some registers. */
339 li r0,0x0000
340 lis r1,0xffff
341 mtspr DEC,r0 /* prevent dec exceptions */
342 mttbl r0 /* prevent fit & wdt exceptions */
343 mttbu r0
344 mtspr TSR,r1 /* clear all timer exception status */
345 mtspr TCR,r0 /* disable all */
346 mtspr ESR,r0 /* clear exception syndrome register */
347 mtspr MCSR,r0 /* machine check syndrome register */
348 mtxer r0 /* clear integer exception register */
349 lis r1,0x0002 /* set CE bit (Critical Exceptions) */
350 ori r1,r1,0x1200 /* set ME/DE bit */
351 mtmsr r1 /* change MSR */
352 isync
353
354 /* Enable Time Base and Select Time Base Clock */
wdenk0ac6f8b2004-07-09 23:27:13 +0000355 lis r0,HID0_EMCP@h /* Enable machine check */
356 ori r0,r0,0x4000 /* time base is processor clock */
wdenk42d1f032003-10-15 23:53:47 +0000357 mtspr HID0,r0
wdenk42d1f032003-10-15 23:53:47 +0000358
359#if defined(CONFIG_ADDR_STREAMING)
wdenka57a4962003-10-26 22:52:58 +0000360 li r0,0x3000
361#else
362 li r0,0x1000
363#endif
wdenk42d1f032003-10-15 23:53:47 +0000364 mtspr HID1,r0
wdenk42d1f032003-10-15 23:53:47 +0000365
366 /* Enable Branch Prediction */
367#if defined(CONFIG_BTB)
368 li r0,0x201 /* BBFI = 1, BPEN = 1 */
369 mtspr BUCSR,r0
wdenk42d1f032003-10-15 23:53:47 +0000370#endif
371
372#if defined(CFG_INIT_DBCR)
373 lis r1,0xffff
374 ori r1,r1,0xffff
wdenk0ac6f8b2004-07-09 23:27:13 +0000375 mtspr DBSR,r1 /* Clear all status bits */
wdenk42d1f032003-10-15 23:53:47 +0000376 lis r0,CFG_INIT_DBCR@h /* DBCR0[IDM] must be set */
377 ori r0,r0,CFG_INIT_DBCR@l
wdenk0ac6f8b2004-07-09 23:27:13 +0000378 mtspr DBCR0,r0
wdenk42d1f032003-10-15 23:53:47 +0000379#endif
380
381/* L1 DCache is used for initial RAM */
382 mfspr r2, L1CSR0
383 ori r2, r2, 0x0003
384 oris r2, r2, 0x0001
wdenk42d1f032003-10-15 23:53:47 +0000385 mtspr L1CSR0, r2 /* enable/invalidate L1 Dcache */
386 isync
387
388 /* Allocate Initial RAM in data cache.
389 */
390 lis r3, CFG_INIT_RAM_ADDR@h
391 ori r3, r3, CFG_INIT_RAM_ADDR@l
392 li r2, 512 /* 512*32=16K */
393 mtctr r2
394 li r0, 0
3951:
396 dcbz r0, r3
397 dcbtls 0,r0, r3
398 addi r3, r3, 32
399 bdnz 1b
400
401#ifndef CFG_RAMBOOT
402 /* Calculate absolute address in FLASH and jump there */
403 /*--------------------------------------------------------------*/
404 lis r3, CFG_MONITOR_BASE@h
405 ori r3, r3, CFG_MONITOR_BASE@l
406 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
407 mtlr r3
408 blr
409
410in_flash:
411#endif /* CFG_RAMBOOT */
412
413 /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
414 lis r1,CFG_INIT_RAM_ADDR@h
415 ori r1,r1,CFG_INIT_SP_OFFSET@l
416
417 li r0,0
418 stwu r0,-4(r1)
419 stwu r0,-4(r1) /* Terminate call chain */
420
421 stwu r1,-8(r1) /* Save back chain and move SP */
422 lis r0,RESET_VECTOR@h /* Address of reset vector */
423 ori r0,r0, RESET_VECTOR@l
424 stwu r1,-8(r1) /* Save back chain and move SP */
425 stw r0,+12(r1) /* Save return addr (underflow vect) */
426
427 GET_GOT
428 bl cpu_init_f
429 bl icache_enable
430 bl board_init_f
wdenk0ac6f8b2004-07-09 23:27:13 +0000431 isync
wdenk42d1f032003-10-15 23:53:47 +0000432
433/* --FIXME-- machine check with MCSRRn and rfmci */
434
435 .globl _start_of_vectors
436_start_of_vectors:
437#if 0
438/* Critical input. */
439 CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
440#endif
441/* Machine check --FIXME-- Should be MACH_EXCEPTION */
442 CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
443
444/* Data Storage exception. */
445 STD_EXCEPTION(0x0300, DataStorage, UnknownException)
446
447/* Instruction Storage exception. */
448 STD_EXCEPTION(0x0400, InstStorage, UnknownException)
449
450/* External Interrupt exception. */
451 STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
452
453/* Alignment exception. */
454 . = 0x0600
455Alignment:
456 EXCEPTION_PROLOG
457 mfspr r4,DAR
458 stw r4,_DAR(r21)
459 mfspr r5,DSISR
460 stw r5,_DSISR(r21)
461 addi r3,r1,STACK_FRAME_OVERHEAD
462 li r20,MSR_KERNEL
463 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
464 lwz r6,GOT(transfer_to_handler)
465 mtlr r6
466 blrl
467.L_Alignment:
468 .long AlignmentException - _start + EXC_OFF_SYS_RESET
469 .long int_return - _start + EXC_OFF_SYS_RESET
470
471/* Program check exception */
472 . = 0x0700
473ProgramCheck:
474 EXCEPTION_PROLOG
475 addi r3,r1,STACK_FRAME_OVERHEAD
476 li r20,MSR_KERNEL
477 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
478 lwz r6,GOT(transfer_to_handler)
479 mtlr r6
480 blrl
481.L_ProgramCheck:
482 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
483 .long int_return - _start + EXC_OFF_SYS_RESET
484
485 /* No FPU on MPC85xx. This exception is not supposed to happen.
486 */
487 STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
488 STD_EXCEPTION(0x0900, Decrementer, timer_interrupt)
489 STD_EXCEPTION(0x0a00, Trap_0a, UnknownException)
490 STD_EXCEPTION(0x0b00, Trap_0b, UnknownException)
491
492 . = 0x0c00
493/*
494 * r0 - SYSCALL number
495 * r3-... arguments
496 */
497SystemCall:
498 addis r11,r0,0 /* get functions table addr */
499 ori r11,r11,0 /* Note: this code is patched in trap_init */
500 addis r12,r0,0 /* get number of functions */
501 ori r12,r12,0
502
503 cmplw 0, r0, r12
504 bge 1f
505
506 rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
507 add r11,r11,r0
508 lwz r11,0(r11)
509
510 li r20,0xd00-4 /* Get stack pointer */
511 lwz r12,0(r20)
512 subi r12,r12,12 /* Adjust stack pointer */
513 li r0,0xc00+_end_back-SystemCall
514 cmplw 0, r0, r12 /* Check stack overflow */
515 bgt 1f
516 stw r12,0(r20)
517
518 mflr r0
519 stw r0,0(r12)
520 mfspr r0,SRR0
521 stw r0,4(r12)
522 mfspr r0,SRR1
523 stw r0,8(r12)
524
525 li r12,0xc00+_back-SystemCall
526 mtlr r12
527 mtspr SRR0,r11
528
5291: SYNC
530 rfi
531_back:
532
533 mfmsr r11 /* Disable interrupts */
534 li r12,0
535 ori r12,r12,MSR_EE
536 andc r11,r11,r12
537 SYNC /* Some chip revs need this... */
538 mtmsr r11
539 SYNC
540
541 li r12,0xd00-4 /* restore regs */
542 lwz r12,0(r12)
543
544 lwz r11,0(r12)
545 mtlr r11
546 lwz r11,4(r12)
547 mtspr SRR0,r11
548 lwz r11,8(r12)
549 mtspr SRR1,r11
550
551 addi r12,r12,12 /* Adjust stack pointer */
552 li r20,0xd00-4
553 stw r12,0(r20)
554
555 SYNC
556 rfi
557_end_back:
558
559 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
560
561 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
562 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
563
564 STD_EXCEPTION(0x1000, PIT, PITException)
565
566 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
567 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
568 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
569 STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
570
571 STD_EXCEPTION(0x1500, Reserved5, UnknownException)
572 STD_EXCEPTION(0x1600, Reserved6, UnknownException)
573 STD_EXCEPTION(0x1700, Reserved7, UnknownException)
574 STD_EXCEPTION(0x1800, Reserved8, UnknownException)
575 STD_EXCEPTION(0x1900, Reserved9, UnknownException)
576 STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
577 STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
578
579 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
580 STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
581 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
582 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
583
584 CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
585
586 .globl _end_of_vectors
587_end_of_vectors:
588
589
590 . = 0x2100
591
592/*
593 * This code finishes saving the registers to the exception frame
594 * and jumps to the appropriate handler for the exception.
595 * Register r21 is pointer into trap frame, r1 has new stack pointer.
596 */
597 .globl transfer_to_handler
598transfer_to_handler:
599 stw r22,_NIP(r21)
600 lis r22,MSR_POW@h
601 andc r23,r23,r22
602 stw r23,_MSR(r21)
603 SAVE_GPR(7, r21)
604 SAVE_4GPRS(8, r21)
605 SAVE_8GPRS(12, r21)
606 SAVE_8GPRS(24, r21)
607
608 mflr r23
609 andi. r24,r23,0x3f00 /* get vector offset */
610 stw r24,TRAP(r21)
611 li r22,0
612 stw r22,RESULT(r21)
613 mtspr SPRG2,r22 /* r1 is now kernel sp */
614
615 lwz r24,0(r23) /* virtual address of handler */
616 lwz r23,4(r23) /* where to go when done */
617 mtspr SRR0,r24
618 mtspr SRR1,r20
619 mtlr r23
620 SYNC
621 rfi /* jump to handler, enable MMU */
622
623int_return:
624 mfmsr r28 /* Disable interrupts */
625 li r4,0
626 ori r4,r4,MSR_EE
627 andc r28,r28,r4
628 SYNC /* Some chip revs need this... */
629 mtmsr r28
630 SYNC
631 lwz r2,_CTR(r1)
632 lwz r0,_LINK(r1)
633 mtctr r2
634 mtlr r0
635 lwz r2,_XER(r1)
636 lwz r0,_CCR(r1)
637 mtspr XER,r2
638 mtcrf 0xFF,r0
639 REST_10GPRS(3, r1)
640 REST_10GPRS(13, r1)
641 REST_8GPRS(23, r1)
642 REST_GPR(31, r1)
643 lwz r2,_NIP(r1) /* Restore environment */
644 lwz r0,_MSR(r1)
645 mtspr SRR0,r2
646 mtspr SRR1,r0
647 lwz r0,GPR0(r1)
648 lwz r2,GPR2(r1)
649 lwz r1,GPR1(r1)
650 SYNC
651 rfi
652
653crit_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 990,r2 /* SRR2 */
676 mtspr 991,r0 /* SRR3 */
677 lwz r0,GPR0(r1)
678 lwz r2,GPR2(r1)
679 lwz r1,GPR1(r1)
680 SYNC
681 rfci
682
683/* Cache functions.
684*/
685invalidate_icache:
686 mfspr r0,L1CSR1
687 ori r0,r0,0x0002
688 mtspr L1CSR1,r0
689 isync
690 blr /* entire I cache */
691
692invalidate_dcache:
693 mfspr r0,L1CSR0
694 ori r0,r0,0x0002
695 msync
696 isync
697 mtspr L1CSR0,r0
698 isync
699 blr
700
701 .globl icache_enable
702icache_enable:
703 mflr r8
704 bl invalidate_icache
705 mtlr r8
706 isync
707 mfspr r4,L1CSR1
708 ori r4,r4,0x0001
709 oris r4,r4,0x0001
710 mtspr L1CSR1,r4
711 isync
712 blr
713
714 .globl icache_disable
715icache_disable:
716 mfspr r0,L1CSR1
717 lis r1,0xfffffffe@h
718 ori r1,r1,0xfffffffe@l
719 and r0,r0,r1
720 mtspr L1CSR1,r0
721 isync
722 blr
723
724 .globl icache_status
725icache_status:
726 mfspr r3,L1CSR1
727 srwi r3, r3, 31 /* >>31 => select bit 0 */
728 blr
729
730 .globl dcache_enable
731dcache_enable:
732 mflr r8
733 bl invalidate_dcache
734 mtlr r8
735 isync
736 mfspr r0,L1CSR0
737 ori r0,r0,0x0001
738 oris r0,r0,0x0001
739 msync
740 isync
741 mtspr L1CSR0,r0
742 isync
743 blr
744
745 .globl dcache_disable
746dcache_disable:
747 mfspr r0,L1CSR0
748 lis r1,0xfffffffe@h
749 ori r1,r1,0xfffffffe@l
750 and r0,r0,r1
751 msync
752 isync
753 mtspr L1CSR0,r0
754 isync
755 blr
756
757 .globl dcache_status
758dcache_status:
759 mfspr r3,L1CSR0
760 srwi r3, r3, 31 /* >>31 => select bit 0 */
761 blr
762
763 .globl get_pir
764get_pir:
765 mfspr r3, PIR
766 blr
767
768 .globl get_pvr
769get_pvr:
770 mfspr r3, PVR
771 blr
772
wdenk97d80fc2004-06-09 00:34:46 +0000773 .globl get_svr
774get_svr:
775 mfspr r3, SVR
776 blr
777
wdenk42d1f032003-10-15 23:53:47 +0000778 .globl wr_tcr
779wr_tcr:
780 mtspr TCR, r3
781 blr
782
783/*------------------------------------------------------------------------------- */
784/* Function: in8 */
785/* Description: Input 8 bits */
786/*------------------------------------------------------------------------------- */
787 .globl in8
788in8:
789 lbz r3,0x0000(r3)
790 blr
791
792/*------------------------------------------------------------------------------- */
793/* Function: out8 */
794/* Description: Output 8 bits */
795/*------------------------------------------------------------------------------- */
796 .globl out8
797out8:
798 stb r4,0x0000(r3)
799 blr
800
801/*------------------------------------------------------------------------------- */
802/* Function: out16 */
803/* Description: Output 16 bits */
804/*------------------------------------------------------------------------------- */
805 .globl out16
806out16:
807 sth r4,0x0000(r3)
808 blr
809
810/*------------------------------------------------------------------------------- */
811/* Function: out16r */
812/* Description: Byte reverse and output 16 bits */
813/*------------------------------------------------------------------------------- */
814 .globl out16r
815out16r:
816 sthbrx r4,r0,r3
817 blr
818
819/*------------------------------------------------------------------------------- */
820/* Function: out32 */
821/* Description: Output 32 bits */
822/*------------------------------------------------------------------------------- */
823 .globl out32
824out32:
825 stw r4,0x0000(r3)
826 blr
827
828/*------------------------------------------------------------------------------- */
829/* Function: out32r */
830/* Description: Byte reverse and output 32 bits */
831/*------------------------------------------------------------------------------- */
832 .globl out32r
833out32r:
834 stwbrx r4,r0,r3
835 blr
836
837/*------------------------------------------------------------------------------- */
838/* Function: in16 */
839/* Description: Input 16 bits */
840/*------------------------------------------------------------------------------- */
841 .globl in16
842in16:
843 lhz r3,0x0000(r3)
844 blr
845
846/*------------------------------------------------------------------------------- */
847/* Function: in16r */
848/* Description: Input 16 bits and byte reverse */
849/*------------------------------------------------------------------------------- */
850 .globl in16r
851in16r:
852 lhbrx r3,r0,r3
853 blr
854
855/*------------------------------------------------------------------------------- */
856/* Function: in32 */
857/* Description: Input 32 bits */
858/*------------------------------------------------------------------------------- */
859 .globl in32
860in32:
861 lwz 3,0x0000(3)
862 blr
863
864/*------------------------------------------------------------------------------- */
865/* Function: in32r */
866/* Description: Input 32 bits and byte reverse */
867/*------------------------------------------------------------------------------- */
868 .globl in32r
869in32r:
870 lwbrx r3,r0,r3
871 blr
872
873/*------------------------------------------------------------------------------- */
874/* Function: ppcDcbf */
875/* Description: Data Cache block flush */
876/* Input: r3 = effective address */
877/* Output: none. */
878/*------------------------------------------------------------------------------- */
879 .globl ppcDcbf
880ppcDcbf:
881 dcbf r0,r3
882 blr
883
884/*------------------------------------------------------------------------------- */
885/* Function: ppcDcbi */
886/* Description: Data Cache block Invalidate */
887/* Input: r3 = effective address */
888/* Output: none. */
889/*------------------------------------------------------------------------------- */
890 .globl ppcDcbi
891ppcDcbi:
892 dcbi r0,r3
893 blr
894
wdenk0ac6f8b2004-07-09 23:27:13 +0000895/*--------------------------------------------------------------------------
896 * Function: ppcDcbz
897 * Description: Data Cache block zero.
898 * Input: r3 = effective address
899 * Output: none.
900 *-------------------------------------------------------------------------- */
901
902 .globl ppcDcbz
903ppcDcbz:
904 dcbz r0,r3
905 blr
906
wdenk42d1f032003-10-15 23:53:47 +0000907/*------------------------------------------------------------------------------- */
908/* Function: ppcSync */
909/* Description: Processor Synchronize */
910/* Input: none. */
911/* Output: none. */
912/*------------------------------------------------------------------------------- */
913 .globl ppcSync
914ppcSync:
915 sync
916 blr
917
918/*------------------------------------------------------------------------------*/
919
920/*
921 * void relocate_code (addr_sp, gd, addr_moni)
922 *
923 * This "function" does not return, instead it continues in RAM
924 * after relocating the monitor code.
925 *
926 * r3 = dest
927 * r4 = src
928 * r5 = length in bytes
929 * r6 = cachelinesize
930 */
931 .globl relocate_code
932relocate_code:
933 mr r1, r3 /* Set new stack pointer */
934 mr r9, r4 /* Save copy of Init Data pointer */
935 mr r10, r5 /* Save copy of Destination Address */
936
937 mr r3, r5 /* Destination Address */
938 lis r4, CFG_MONITOR_BASE@h /* Source Address */
939 ori r4, r4, CFG_MONITOR_BASE@l
940 lwz r5,GOT(__init_end)
941 sub r5,r5,r4
942 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
943
944 /*
945 * Fix GOT pointer:
946 *
947 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
948 *
949 * Offset:
950 */
951 sub r15, r10, r4
952
953 /* First our own GOT */
954 add r14, r14, r15
955 /* the the one used by the C code */
956 add r30, r30, r15
957
958 /*
959 * Now relocate code
960 */
961
962 cmplw cr1,r3,r4
963 addi r0,r5,3
964 srwi. r0,r0,2
965 beq cr1,4f /* In place copy is not necessary */
966 beq 7f /* Protect against 0 count */
967 mtctr r0
968 bge cr1,2f
969
970 la r8,-4(r4)
971 la r7,-4(r3)
9721: lwzu r0,4(r8)
973 stwu r0,4(r7)
974 bdnz 1b
975 b 4f
976
9772: slwi r0,r0,2
978 add r8,r4,r0
979 add r7,r3,r0
9803: lwzu r0,-4(r8)
981 stwu r0,-4(r7)
982 bdnz 3b
983
984/*
985 * Now flush the cache: note that we must start from a cache aligned
986 * address. Otherwise we might miss one cache line.
987 */
9884: cmpwi r6,0
989 add r5,r3,r5
990 beq 7f /* Always flush prefetch queue in any case */
991 subi r0,r6,1
992 andc r3,r3,r0
993 mr r4,r3
9945: dcbst 0,r4
995 add r4,r4,r6
996 cmplw r4,r5
997 blt 5b
998 sync /* Wait for all dcbst to complete on bus */
999 mr r4,r3
10006: icbi 0,r4
1001 add r4,r4,r6
1002 cmplw r4,r5
1003 blt 6b
10047: sync /* Wait for all icbi to complete on bus */
1005 isync
1006
1007/*
1008 * We are done. Do not return, instead branch to second part of board
1009 * initialization, now running from RAM.
1010 */
1011
1012 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1013 mtlr r0
1014 blr /* NEVER RETURNS! */
1015
1016in_ram:
1017
1018 /*
1019 * Relocation Function, r14 point to got2+0x8000
1020 *
1021 * Adjust got2 pointers, no need to check for 0, this code
1022 * already puts a few entries in the table.
1023 */
1024 li r0,__got2_entries@sectoff@l
1025 la r3,GOT(_GOT2_TABLE_)
1026 lwz r11,GOT(_GOT2_TABLE_)
1027 mtctr r0
1028 sub r11,r3,r11
1029 addi r3,r3,-4
10301: lwzu r0,4(r3)
1031 add r0,r0,r11
1032 stw r0,0(r3)
1033 bdnz 1b
1034
1035 /*
1036 * Now adjust the fixups and the pointers to the fixups
1037 * in case we need to move ourselves again.
1038 */
10392: li r0,__fixup_entries@sectoff@l
1040 lwz r3,GOT(_FIXUP_TABLE_)
1041 cmpwi r0,0
1042 mtctr r0
1043 addi r3,r3,-4
1044 beq 4f
10453: lwzu r4,4(r3)
1046 lwzux r0,r4,r11
1047 add r0,r0,r11
1048 stw r10,0(r3)
1049 stw r0,0(r4)
1050 bdnz 3b
10514:
1052clear_bss:
1053 /*
1054 * Now clear BSS segment
1055 */
1056 lwz r3,GOT(__bss_start)
1057 lwz r4,GOT(_end)
1058
1059 cmplw 0, r3, r4
1060 beq 6f
1061
1062 li r0, 0
10635:
1064 stw r0, 0(r3)
1065 addi r3, r3, 4
1066 cmplw 0, r3, r4
1067 bne 5b
10686:
1069
1070 mr r3, r9 /* Init Data pointer */
1071 mr r4, r10 /* Destination Address */
1072 bl board_init_r
1073
1074 /*
1075 * Copy exception vector code to low memory
1076 *
1077 * r3: dest_addr
1078 * r7: source address, r8: end address, r9: target address
1079 */
1080 .globl trap_init
1081trap_init:
1082 lwz r7, GOT(_start)
1083 lwz r8, GOT(_end_of_vectors)
1084
1085 li r9, 0x100 /* reset vector always at 0x100 */
1086
1087 cmplw 0, r7, r8
1088 bgelr /* return if r7>=r8 - just in case */
1089
1090 mflr r4 /* save link register */
10911:
1092 lwz r0, 0(r7)
1093 stw r0, 0(r9)
1094 addi r7, r7, 4
1095 addi r9, r9, 4
1096 cmplw 0, r7, r8
1097 bne 1b
1098
1099 /*
1100 * relocate `hdlr' and `int_return' entries
1101 */
1102 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1103 li r8, Alignment - _start + EXC_OFF_SYS_RESET
11042:
1105 bl trap_reloc
1106 addi r7, r7, 0x100 /* next exception vector */
1107 cmplw 0, r7, r8
1108 blt 2b
1109
1110 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1111 bl trap_reloc
1112
1113 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1114 bl trap_reloc
1115
1116 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1117 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
11183:
1119 bl trap_reloc
1120 addi r7, r7, 0x100 /* next exception vector */
1121 cmplw 0, r7, r8
1122 blt 3b
1123
1124 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1125 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
11264:
1127 bl trap_reloc
1128 addi r7, r7, 0x100 /* next exception vector */
1129 cmplw 0, r7, r8
1130 blt 4b
1131
1132 mtlr r4 /* restore link register */
1133 blr
1134
1135 /*
1136 * Function: relocate entries for one exception vector
1137 */
1138trap_reloc:
1139 lwz r0, 0(r7) /* hdlr ... */
1140 add r0, r0, r3 /* ... += dest_addr */
1141 stw r0, 0(r7)
1142
1143 lwz r0, 4(r7) /* int_return ... */
1144 add r0, r0, r3 /* ... += dest_addr */
1145 stw r0, 4(r7)
1146
1147 blr
1148
1149#ifdef CFG_INIT_RAM_LOCK
1150.globl unlock_ram_in_cache
1151unlock_ram_in_cache:
1152 /* invalidate the INIT_RAM section */
1153 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1154 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1155 li r2,512
1156 mtctr r2
11571: icbi r0, r3
1158 dcbi r0, r3
1159 addi r3, r3, 32
1160 bdnz 1b
1161 sync /* Wait for all icbi to complete on bus */
1162 isync
1163 blr
1164#endif