blob: 2f2bd3ad52a0ef37141e24c4f7bfe3ba3dc03e9f [file] [log] [blame]
wdenk9c53f402003-10-15 23:53:47 +00001/*
wdenka445ddf2004-06-09 00:34:46 +00002 * Copyright 2004 Freescale Semiconductor.
wdenk9c53f402003-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:
wdenka445ddf2004-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 */
wdenk9c53f402003-10-15 23:53:47 +000094 li r0,0x2000
95 mtspr 977,r0
wdenk9c53f402003-10-15 23:53:47 +000096
wdenka445ddf2004-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".
wdenk9c53f402003-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
wdenka445ddf2004-06-09 00:34:46 +0000117 * E500: isync after BBEAR,BBTAR,BUCSR,DBCR0,DBCR1,HID0,HID1,
wdenkf3da7cc2005-05-13 22:49:36 +0000118 * L1CSR0, L1CSR1, MAS[0,1,2,3,4,6],MMUCSR0, PID[0,1,2],
119 * SPEFCSR
wdenk9c53f402003-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
wdenk9c53f402003-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 */
wdenk9c53f402003-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
Lunsheng Wang61e61952005-07-29 10:20:29 -0500158 /* not needed and conflicts with some debuggers */
159 /* mtspr DBCR0,r0 */
wdenk9c53f402003-10-15 23:53:47 +0000160 mtspr DBCR1,r0
wdenk9c53f402003-10-15 23:53:47 +0000161 mtspr DBCR2,r0
Lunsheng Wang61e61952005-07-29 10:20:29 -0500162 /* not needed and conflicts with some debuggers */
163 /* mtspr IAC1,r0 */
164 /* mtspr IAC2,r0 */
wdenk9c53f402003-10-15 23:53:47 +0000165 mtspr DAC1,r0
166 mtspr DAC2,r0
167
168 mfspr r1,DBSR
169 mtspr DBSR,r1 /* Clear all valid bits */
170
wdenk9c53f402003-10-15 23:53:47 +0000171 mtspr PID0,r0
wdenk9c53f402003-10-15 23:53:47 +0000172 mtspr PID1,r0
wdenk9c53f402003-10-15 23:53:47 +0000173 mtspr PID2,r0
wdenk9c53f402003-10-15 23:53:47 +0000174 mtspr TCR,r0
175
176 mtspr BUCSR,r0 /* disable branch prediction */
wdenkf3da7cc2005-05-13 22:49:36 +0000177 mtspr MAS4,r0
178 mtspr MAS6,r0
Jon Loeliger77a4f6e2005-07-25 14:05:07 -0500179#if defined(CONFIG_ENABLE_36BIT_PHYS)
180 mtspr MAS7,r0
181#endif
wdenk9c53f402003-10-15 23:53:47 +0000182 isync
183
184 /* Setup interrupt vectors */
wdenkf3da7cc2005-05-13 22:49:36 +0000185 lis r1,TEXT_BASE@h
wdenka445ddf2004-06-09 00:34:46 +0000186 mtspr IVPR, r1
wdenk9c53f402003-10-15 23:53:47 +0000187
wdenkf3da7cc2005-05-13 22:49:36 +0000188 li r1,0x0100
wdenk9c53f402003-10-15 23:53:47 +0000189 mtspr IVOR0,r1 /* 0: Critical input */
wdenkf3da7cc2005-05-13 22:49:36 +0000190 li r1,0x0200
wdenk9c53f402003-10-15 23:53:47 +0000191 mtspr IVOR1,r1 /* 1: Machine check */
wdenkf3da7cc2005-05-13 22:49:36 +0000192 li r1,0x0300
wdenk9c53f402003-10-15 23:53:47 +0000193 mtspr IVOR2,r1 /* 2: Data storage */
wdenkf3da7cc2005-05-13 22:49:36 +0000194 li r1,0x0400
wdenk9c53f402003-10-15 23:53:47 +0000195 mtspr IVOR3,r1 /* 3: Instruction storage */
196 li r1,0x0500
197 mtspr IVOR4,r1 /* 4: External interrupt */
198 li r1,0x0600
199 mtspr IVOR5,r1 /* 5: Alignment */
200 li r1,0x0700
201 mtspr IVOR6,r1 /* 6: Program check */
202 li r1,0x0800
203 mtspr IVOR7,r1 /* 7: floating point unavailable */
wdenkf3da7cc2005-05-13 22:49:36 +0000204 li r1,0x0900
wdenk9c53f402003-10-15 23:53:47 +0000205 mtspr IVOR8,r1 /* 8: System call */
206 /* 9: Auxiliary processor unavailable(unsupported) */
wdenkf3da7cc2005-05-13 22:49:36 +0000207 li r1,0x0a00
wdenk9c53f402003-10-15 23:53:47 +0000208 mtspr IVOR10,r1 /* 10: Decrementer */
wdenkf3da7cc2005-05-13 22:49:36 +0000209 li r1,0x0b00
210 mtspr IVOR11,r1 /* 11: Interval timer */
211 li r1,0x0c00
Wolfgang Denkc94dea22005-08-04 01:24:19 +0200212 mtspr IVOR12,r1 /* 12: Watchdog timer */
213 li r1,0x0d00
wdenk9c53f402003-10-15 23:53:47 +0000214 mtspr IVOR13,r1 /* 13: Data TLB error */
wdenkf3da7cc2005-05-13 22:49:36 +0000215 li r1,0x0e00
wdenk9c53f402003-10-15 23:53:47 +0000216 mtspr IVOR14,r1 /* 14: Instruction TLB error */
wdenkf3da7cc2005-05-13 22:49:36 +0000217 li r1,0x0f00
wdenk9c53f402003-10-15 23:53:47 +0000218 mtspr IVOR15,r1 /* 15: Debug */
219
wdenka445ddf2004-06-09 00:34:46 +0000220 /*
221 * Invalidate MMU L1/L2
222 *
223 * Note: There is a fixup earlier for Errata CPU4 on
224 * Rev 1 parts that must precede this MMU invalidation.
wdenk9c53f402003-10-15 23:53:47 +0000225 */
wdenkf3da7cc2005-05-13 22:49:36 +0000226 li r2, 0x001e
227 mtspr MMUCSR0, r2
wdenk9c53f402003-10-15 23:53:47 +0000228 isync
wdenk9c53f402003-10-15 23:53:47 +0000229
wdenk492b9e72004-08-01 23:02:45 +0000230 /*
231 * Invalidate all TLB0 entries.
232 */
wdenkf3da7cc2005-05-13 22:49:36 +0000233 li r3,4
wdenk492b9e72004-08-01 23:02:45 +0000234 li r4,0
wdenkf3da7cc2005-05-13 22:49:36 +0000235 tlbivax r4,r3
wdenk492b9e72004-08-01 23:02:45 +0000236 /*
237 * To avoid REV1 Errata CPU6 issues, make sure
238 * the instruction following tlbivax is not a store.
239 */
240
241 /*
242 * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
wdenk9c53f402003-10-15 23:53:47 +0000243 * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
244 * region before we can access any CCSR registers such as L2
245 * registers, Local Access Registers,etc. We will also re-allocate
246 * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
247 *
248 * Please refer to board-specif directory for TLB1 entry configuration.
249 * (e.g. board/<yourboard>/init.S)
250 *
251 */
wdenkf3da7cc2005-05-13 22:49:36 +0000252 bl tlb1_entry
wdenk9c53f402003-10-15 23:53:47 +0000253 mr r5,r0
wdenk492b9e72004-08-01 23:02:45 +0000254 li r1,0x0020 /* max 16 TLB1 plus some TLB0 entries */
wdenk9c53f402003-10-15 23:53:47 +0000255 mtctr r1
256 lwzu r4,0(r5) /* how many TLB1 entries we actually use */
257
2580: cmpwi r4,0
259 beq 1f
260 lwzu r0,4(r5)
261 lwzu r1,4(r5)
262 lwzu r2,4(r5)
263 lwzu r3,4(r5)
264 mtspr MAS0,r0
265 mtspr MAS1,r1
266 mtspr MAS2,r2
267 mtspr MAS3,r3
268 isync
269 msync
270 tlbwe
271 isync
272 addi r4,r4,-1
273 bdnz 0b
274
2751:
276#if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
277 /* Special sequence needed to update CCSRBAR itself */
278 lis r4, CFG_CCSRBAR_DEFAULT@h
279 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
280
wdenkf3da7cc2005-05-13 22:49:36 +0000281 lis r5, CFG_CCSRBAR@h
282 ori r5, r5, CFG_CCSRBAR@l
wdenk9c53f402003-10-15 23:53:47 +0000283 srwi r6,r5,12
284 stw r6, 0(r4)
285 isync
286
287 lis r5, 0xffff
288 ori r5,r5,0xf000
289 lwz r5, 0(r5)
290 isync
291
292 lis r3, CFG_CCSRBAR@h
293 lwz r5, CFG_CCSRBAR@l(r3)
294 isync
295#endif
296
wdenk9c53f402003-10-15 23:53:47 +0000297
298 /* set up local access windows, defined at board/<boardname>/init.S */
299 lis r7,CFG_CCSRBAR@h
300 ori r7,r7,CFG_CCSRBAR@l
301
wdenkf3da7cc2005-05-13 22:49:36 +0000302 bl law_entry
wdenk9c53f402003-10-15 23:53:47 +0000303 mr r6,r0
wdenk492b9e72004-08-01 23:02:45 +0000304 li r1,0x0007 /* 8 LAWs, but reserve one for boot-over-rio-or-pci */
wdenk9c53f402003-10-15 23:53:47 +0000305 mtctr r1
306 lwzu r5,0(r6) /* how many windows we actually use */
307
wdenk9c53f402003-10-15 23:53:47 +0000308 li r2,0x0c28 /* the first pair is reserved for boot-over-rio-or-pci */
309 li r1,0x0c30
wdenk9c53f402003-10-15 23:53:47 +0000310
3110: cmpwi r5,0
312 beq 1f
313 lwzu r4,4(r6)
314 lwzu r3,4(r6)
315 stwx r4,r7,r2
316 stwx r3,r7,r1
317 addi r5,r5,-1
318 addi r2,r2,0x0020
319 addi r1,r1,0x0020
320 bdnz 0b
321
322 /* Jump out the last 4K page and continue to 'normal' start */
3231: bl 3f
324 b _start
325
3263: li r0,0
327 mtspr SRR1,r0 /* Keep things disabled for now */
328 mflr r1
329 mtspr SRR0,r1
330 rfi
331
332/*
333 * r3 - 1st arg to board_init(): IMMP pointer
334 * r4 - 2nd arg to board_init(): boot flag
335 */
336 .text
337 .long 0x27051956 /* U-BOOT Magic Number */
338 .globl version_string
339version_string:
340 .ascii U_BOOT_VERSION
341 .ascii " (", __DATE__, " - ", __TIME__, ")"
342 .ascii CONFIG_IDENT_STRING, "\0"
343
344 . = EXC_OFF_SYS_RESET
345 .globl _start
346_start:
347 /* Clear and set up some registers. */
348 li r0,0x0000
349 lis r1,0xffff
350 mtspr DEC,r0 /* prevent dec exceptions */
351 mttbl r0 /* prevent fit & wdt exceptions */
352 mttbu r0
353 mtspr TSR,r1 /* clear all timer exception status */
354 mtspr TCR,r0 /* disable all */
355 mtspr ESR,r0 /* clear exception syndrome register */
356 mtspr MCSR,r0 /* machine check syndrome register */
357 mtxer r0 /* clear integer exception register */
358 lis r1,0x0002 /* set CE bit (Critical Exceptions) */
359 ori r1,r1,0x1200 /* set ME/DE bit */
360 mtmsr r1 /* change MSR */
361 isync
362
363 /* Enable Time Base and Select Time Base Clock */
wdenk13eb2212004-07-09 23:27:13 +0000364 lis r0,HID0_EMCP@h /* Enable machine check */
365 ori r0,r0,0x4000 /* time base is processor clock */
Jon Loeliger77a4f6e2005-07-25 14:05:07 -0500366#if defined(CONFIG_ENABLE_36BIT_PHYS)
367 ori r0,r0,0x0080 /* enable MAS7 updates */
368#endif
wdenk9c53f402003-10-15 23:53:47 +0000369 mtspr HID0,r0
wdenk9c53f402003-10-15 23:53:47 +0000370
371#if defined(CONFIG_ADDR_STREAMING)
wdenka983cc22003-10-26 22:52:58 +0000372 li r0,0x3000
373#else
374 li r0,0x1000
375#endif
wdenk9c53f402003-10-15 23:53:47 +0000376 mtspr HID1,r0
wdenk9c53f402003-10-15 23:53:47 +0000377
378 /* Enable Branch Prediction */
379#if defined(CONFIG_BTB)
380 li r0,0x201 /* BBFI = 1, BPEN = 1 */
381 mtspr BUCSR,r0
wdenk9c53f402003-10-15 23:53:47 +0000382#endif
383
384#if defined(CFG_INIT_DBCR)
385 lis r1,0xffff
386 ori r1,r1,0xffff
wdenk13eb2212004-07-09 23:27:13 +0000387 mtspr DBSR,r1 /* Clear all status bits */
wdenk9c53f402003-10-15 23:53:47 +0000388 lis r0,CFG_INIT_DBCR@h /* DBCR0[IDM] must be set */
389 ori r0,r0,CFG_INIT_DBCR@l
wdenk13eb2212004-07-09 23:27:13 +0000390 mtspr DBCR0,r0
wdenk9c53f402003-10-15 23:53:47 +0000391#endif
392
393/* L1 DCache is used for initial RAM */
394 mfspr r2, L1CSR0
wdenkf3da7cc2005-05-13 22:49:36 +0000395 ori r2, r2, 0x0003
396 oris r2, r2, 0x0001
397 mtspr L1CSR0, r2 /* enable/invalidate L1 Dcache */
wdenk9c53f402003-10-15 23:53:47 +0000398 isync
399
400 /* Allocate Initial RAM in data cache.
401 */
wdenkf3da7cc2005-05-13 22:49:36 +0000402 lis r3, CFG_INIT_RAM_ADDR@h
403 ori r3, r3, CFG_INIT_RAM_ADDR@l
404 li r2, 512 /* 512*32=16K */
405 mtctr r2
wdenk9c53f402003-10-15 23:53:47 +0000406 li r0, 0
4071:
408 dcbz r0, r3
wdenkf3da7cc2005-05-13 22:49:36 +0000409 dcbtls 0,r0, r3
410 addi r3, r3, 32
411 bdnz 1b
wdenk9c53f402003-10-15 23:53:47 +0000412
413#ifndef CFG_RAMBOOT
wdenkf3da7cc2005-05-13 22:49:36 +0000414 /* Calculate absolute address in FLASH and jump there */
wdenk9c53f402003-10-15 23:53:47 +0000415 /*--------------------------------------------------------------*/
wdenkf3da7cc2005-05-13 22:49:36 +0000416 lis r3, CFG_MONITOR_BASE@h
417 ori r3, r3, CFG_MONITOR_BASE@l
418 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
419 mtlr r3
wdenk9c53f402003-10-15 23:53:47 +0000420 blr
421
422in_flash:
wdenkf3da7cc2005-05-13 22:49:36 +0000423#endif /* CFG_RAMBOOT */
wdenk9c53f402003-10-15 23:53:47 +0000424
425 /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
426 lis r1,CFG_INIT_RAM_ADDR@h
427 ori r1,r1,CFG_INIT_SP_OFFSET@l
428
429 li r0,0
430 stwu r0,-4(r1)
431 stwu r0,-4(r1) /* Terminate call chain */
432
433 stwu r1,-8(r1) /* Save back chain and move SP */
434 lis r0,RESET_VECTOR@h /* Address of reset vector */
435 ori r0,r0, RESET_VECTOR@l
436 stwu r1,-8(r1) /* Save back chain and move SP */
437 stw r0,+12(r1) /* Save return addr (underflow vect) */
438
439 GET_GOT
440 bl cpu_init_f
441 bl icache_enable
442 bl board_init_f
wdenk13eb2212004-07-09 23:27:13 +0000443 isync
wdenk9c53f402003-10-15 23:53:47 +0000444
445/* --FIXME-- machine check with MCSRRn and rfmci */
446
447 .globl _start_of_vectors
448_start_of_vectors:
449#if 0
450/* Critical input. */
451 CRIT_EXCEPTION(0x0100, CritcalInput, CritcalInputException)
452#endif
453/* Machine check --FIXME-- Should be MACH_EXCEPTION */
454 CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
455
456/* Data Storage exception. */
457 STD_EXCEPTION(0x0300, DataStorage, UnknownException)
458
459/* Instruction Storage exception. */
460 STD_EXCEPTION(0x0400, InstStorage, UnknownException)
461
462/* External Interrupt exception. */
463 STD_EXCEPTION(0x0500, ExtInterrupt, UnknownException)
464
465/* Alignment exception. */
466 . = 0x0600
467Alignment:
468 EXCEPTION_PROLOG
469 mfspr r4,DAR
470 stw r4,_DAR(r21)
471 mfspr r5,DSISR
472 stw r5,_DSISR(r21)
473 addi r3,r1,STACK_FRAME_OVERHEAD
474 li r20,MSR_KERNEL
475 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
476 lwz r6,GOT(transfer_to_handler)
477 mtlr r6
478 blrl
479.L_Alignment:
480 .long AlignmentException - _start + EXC_OFF_SYS_RESET
481 .long int_return - _start + EXC_OFF_SYS_RESET
482
483/* Program check exception */
484 . = 0x0700
485ProgramCheck:
486 EXCEPTION_PROLOG
487 addi r3,r1,STACK_FRAME_OVERHEAD
488 li r20,MSR_KERNEL
489 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
490 lwz r6,GOT(transfer_to_handler)
491 mtlr r6
492 blrl
493.L_ProgramCheck:
494 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
495 .long int_return - _start + EXC_OFF_SYS_RESET
496
497 /* No FPU on MPC85xx. This exception is not supposed to happen.
498 */
499 STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
wdenk9c53f402003-10-15 23:53:47 +0000500
wdenkf3da7cc2005-05-13 22:49:36 +0000501 . = 0x0900
wdenk9c53f402003-10-15 23:53:47 +0000502/*
503 * r0 - SYSCALL number
504 * r3-... arguments
505 */
506SystemCall:
wdenkf3da7cc2005-05-13 22:49:36 +0000507 addis r11,r0,0 /* get functions table addr */
508 ori r11,r11,0 /* Note: this code is patched in trap_init */
509 addis r12,r0,0 /* get number of functions */
510 ori r12,r12,0
wdenk9c53f402003-10-15 23:53:47 +0000511
wdenkf3da7cc2005-05-13 22:49:36 +0000512 cmplw 0, r0, r12
513 bge 1f
wdenk9c53f402003-10-15 23:53:47 +0000514
wdenkf3da7cc2005-05-13 22:49:36 +0000515 rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
516 add r11,r11,r0
517 lwz r11,0(r11)
wdenk9c53f402003-10-15 23:53:47 +0000518
wdenkf3da7cc2005-05-13 22:49:36 +0000519 li r20,0xd00-4 /* Get stack pointer */
520 lwz r12,0(r20)
521 subi r12,r12,12 /* Adjust stack pointer */
522 li r0,0xc00+_end_back-SystemCall
523 cmplw 0, r0, r12 /* Check stack overflow */
524 bgt 1f
525 stw r12,0(r20)
wdenk9c53f402003-10-15 23:53:47 +0000526
wdenkf3da7cc2005-05-13 22:49:36 +0000527 mflr r0
528 stw r0,0(r12)
529 mfspr r0,SRR0
530 stw r0,4(r12)
531 mfspr r0,SRR1
532 stw r0,8(r12)
wdenk9c53f402003-10-15 23:53:47 +0000533
wdenkf3da7cc2005-05-13 22:49:36 +0000534 li r12,0xc00+_back-SystemCall
535 mtlr r12
536 mtspr SRR0,r11
wdenk9c53f402003-10-15 23:53:47 +0000537
wdenkf3da7cc2005-05-13 22:49:36 +00005381: SYNC
wdenk9c53f402003-10-15 23:53:47 +0000539 rfi
540_back:
541
wdenkf3da7cc2005-05-13 22:49:36 +0000542 mfmsr r11 /* Disable interrupts */
543 li r12,0
544 ori r12,r12,MSR_EE
545 andc r11,r11,r12
546 SYNC /* Some chip revs need this... */
547 mtmsr r11
wdenk9c53f402003-10-15 23:53:47 +0000548 SYNC
549
wdenkf3da7cc2005-05-13 22:49:36 +0000550 li r12,0xd00-4 /* restore regs */
551 lwz r12,0(r12)
wdenk9c53f402003-10-15 23:53:47 +0000552
wdenkf3da7cc2005-05-13 22:49:36 +0000553 lwz r11,0(r12)
554 mtlr r11
555 lwz r11,4(r12)
556 mtspr SRR0,r11
557 lwz r11,8(r12)
558 mtspr SRR1,r11
wdenk9c53f402003-10-15 23:53:47 +0000559
wdenkf3da7cc2005-05-13 22:49:36 +0000560 addi r12,r12,12 /* Adjust stack pointer */
561 li r20,0xd00-4
562 stw r12,0(r20)
wdenk9c53f402003-10-15 23:53:47 +0000563
564 SYNC
565 rfi
566_end_back:
567
wdenkf3da7cc2005-05-13 22:49:36 +0000568 STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
569 STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
570 STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
wdenk9c53f402003-10-15 23:53:47 +0000571
wdenkf3da7cc2005-05-13 22:49:36 +0000572 STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
573 STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
wdenk9c53f402003-10-15 23:53:47 +0000574
wdenkf3da7cc2005-05-13 22:49:36 +0000575 CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
wdenk9c53f402003-10-15 23:53:47 +0000576
wdenkf3da7cc2005-05-13 22:49:36 +0000577 .globl _end_of_vectors
wdenk9c53f402003-10-15 23:53:47 +0000578_end_of_vectors:
579
580
581 . = 0x2100
582
583/*
584 * This code finishes saving the registers to the exception frame
585 * and jumps to the appropriate handler for the exception.
586 * Register r21 is pointer into trap frame, r1 has new stack pointer.
587 */
588 .globl transfer_to_handler
589transfer_to_handler:
590 stw r22,_NIP(r21)
591 lis r22,MSR_POW@h
592 andc r23,r23,r22
593 stw r23,_MSR(r21)
594 SAVE_GPR(7, r21)
595 SAVE_4GPRS(8, r21)
596 SAVE_8GPRS(12, r21)
597 SAVE_8GPRS(24, r21)
598
599 mflr r23
600 andi. r24,r23,0x3f00 /* get vector offset */
601 stw r24,TRAP(r21)
602 li r22,0
603 stw r22,RESULT(r21)
604 mtspr SPRG2,r22 /* r1 is now kernel sp */
605
606 lwz r24,0(r23) /* virtual address of handler */
607 lwz r23,4(r23) /* where to go when done */
608 mtspr SRR0,r24
609 mtspr SRR1,r20
610 mtlr r23
611 SYNC
612 rfi /* jump to handler, enable MMU */
613
614int_return:
615 mfmsr r28 /* Disable interrupts */
616 li r4,0
617 ori r4,r4,MSR_EE
618 andc r28,r28,r4
619 SYNC /* Some chip revs need this... */
620 mtmsr r28
621 SYNC
622 lwz r2,_CTR(r1)
623 lwz r0,_LINK(r1)
624 mtctr r2
625 mtlr r0
626 lwz r2,_XER(r1)
627 lwz r0,_CCR(r1)
628 mtspr XER,r2
629 mtcrf 0xFF,r0
630 REST_10GPRS(3, r1)
631 REST_10GPRS(13, r1)
632 REST_8GPRS(23, r1)
633 REST_GPR(31, r1)
634 lwz r2,_NIP(r1) /* Restore environment */
635 lwz r0,_MSR(r1)
636 mtspr SRR0,r2
637 mtspr SRR1,r0
638 lwz r0,GPR0(r1)
639 lwz r2,GPR2(r1)
640 lwz r1,GPR1(r1)
641 SYNC
642 rfi
643
644crit_return:
645 mfmsr r28 /* Disable interrupts */
646 li r4,0
647 ori r4,r4,MSR_EE
648 andc r28,r28,r4
649 SYNC /* Some chip revs need this... */
650 mtmsr r28
651 SYNC
652 lwz r2,_CTR(r1)
653 lwz r0,_LINK(r1)
654 mtctr r2
655 mtlr r0
656 lwz r2,_XER(r1)
657 lwz r0,_CCR(r1)
658 mtspr XER,r2
659 mtcrf 0xFF,r0
660 REST_10GPRS(3, r1)
661 REST_10GPRS(13, r1)
662 REST_8GPRS(23, r1)
663 REST_GPR(31, r1)
664 lwz r2,_NIP(r1) /* Restore environment */
665 lwz r0,_MSR(r1)
666 mtspr 990,r2 /* SRR2 */
667 mtspr 991,r0 /* SRR3 */
668 lwz r0,GPR0(r1)
669 lwz r2,GPR2(r1)
670 lwz r1,GPR1(r1)
671 SYNC
672 rfci
673
674/* Cache functions.
675*/
676invalidate_icache:
677 mfspr r0,L1CSR1
678 ori r0,r0,0x0002
679 mtspr L1CSR1,r0
680 isync
681 blr /* entire I cache */
682
683invalidate_dcache:
684 mfspr r0,L1CSR0
685 ori r0,r0,0x0002
686 msync
687 isync
688 mtspr L1CSR0,r0
689 isync
690 blr
691
692 .globl icache_enable
693icache_enable:
694 mflr r8
695 bl invalidate_icache
696 mtlr r8
697 isync
698 mfspr r4,L1CSR1
699 ori r4,r4,0x0001
700 oris r4,r4,0x0001
701 mtspr L1CSR1,r4
702 isync
703 blr
704
705 .globl icache_disable
706icache_disable:
707 mfspr r0,L1CSR1
708 lis r1,0xfffffffe@h
709 ori r1,r1,0xfffffffe@l
710 and r0,r0,r1
711 mtspr L1CSR1,r0
712 isync
713 blr
714
715 .globl icache_status
716icache_status:
717 mfspr r3,L1CSR1
718 srwi r3, r3, 31 /* >>31 => select bit 0 */
719 blr
720
721 .globl dcache_enable
722dcache_enable:
723 mflr r8
724 bl invalidate_dcache
725 mtlr r8
726 isync
727 mfspr r0,L1CSR0
728 ori r0,r0,0x0001
729 oris r0,r0,0x0001
730 msync
731 isync
732 mtspr L1CSR0,r0
733 isync
734 blr
735
736 .globl dcache_disable
737dcache_disable:
738 mfspr r0,L1CSR0
739 lis r1,0xfffffffe@h
740 ori r1,r1,0xfffffffe@l
741 and r0,r0,r1
742 msync
743 isync
744 mtspr L1CSR0,r0
745 isync
746 blr
747
748 .globl dcache_status
749dcache_status:
750 mfspr r3,L1CSR0
751 srwi r3, r3, 31 /* >>31 => select bit 0 */
752 blr
753
754 .globl get_pir
755get_pir:
756 mfspr r3, PIR
757 blr
758
759 .globl get_pvr
760get_pvr:
761 mfspr r3, PVR
762 blr
763
wdenka445ddf2004-06-09 00:34:46 +0000764 .globl get_svr
765get_svr:
766 mfspr r3, SVR
767 blr
768
wdenk9c53f402003-10-15 23:53:47 +0000769 .globl wr_tcr
770wr_tcr:
771 mtspr TCR, r3
772 blr
773
774/*------------------------------------------------------------------------------- */
775/* Function: in8 */
776/* Description: Input 8 bits */
777/*------------------------------------------------------------------------------- */
778 .globl in8
779in8:
780 lbz r3,0x0000(r3)
781 blr
782
783/*------------------------------------------------------------------------------- */
784/* Function: out8 */
785/* Description: Output 8 bits */
786/*------------------------------------------------------------------------------- */
787 .globl out8
788out8:
789 stb r4,0x0000(r3)
790 blr
791
792/*------------------------------------------------------------------------------- */
793/* Function: out16 */
794/* Description: Output 16 bits */
795/*------------------------------------------------------------------------------- */
796 .globl out16
797out16:
798 sth r4,0x0000(r3)
799 blr
800
801/*------------------------------------------------------------------------------- */
802/* Function: out16r */
803/* Description: Byte reverse and output 16 bits */
804/*------------------------------------------------------------------------------- */
805 .globl out16r
806out16r:
807 sthbrx r4,r0,r3
808 blr
809
810/*------------------------------------------------------------------------------- */
811/* Function: out32 */
812/* Description: Output 32 bits */
813/*------------------------------------------------------------------------------- */
814 .globl out32
815out32:
816 stw r4,0x0000(r3)
817 blr
818
819/*------------------------------------------------------------------------------- */
820/* Function: out32r */
821/* Description: Byte reverse and output 32 bits */
822/*------------------------------------------------------------------------------- */
823 .globl out32r
824out32r:
825 stwbrx r4,r0,r3
826 blr
827
828/*------------------------------------------------------------------------------- */
829/* Function: in16 */
830/* Description: Input 16 bits */
831/*------------------------------------------------------------------------------- */
832 .globl in16
833in16:
834 lhz r3,0x0000(r3)
835 blr
836
837/*------------------------------------------------------------------------------- */
838/* Function: in16r */
839/* Description: Input 16 bits and byte reverse */
840/*------------------------------------------------------------------------------- */
841 .globl in16r
842in16r:
843 lhbrx r3,r0,r3
844 blr
845
846/*------------------------------------------------------------------------------- */
847/* Function: in32 */
848/* Description: Input 32 bits */
849/*------------------------------------------------------------------------------- */
850 .globl in32
851in32:
852 lwz 3,0x0000(3)
853 blr
854
855/*------------------------------------------------------------------------------- */
856/* Function: in32r */
857/* Description: Input 32 bits and byte reverse */
858/*------------------------------------------------------------------------------- */
859 .globl in32r
860in32r:
861 lwbrx r3,r0,r3
862 blr
863
864/*------------------------------------------------------------------------------- */
865/* Function: ppcDcbf */
866/* Description: Data Cache block flush */
867/* Input: r3 = effective address */
868/* Output: none. */
869/*------------------------------------------------------------------------------- */
870 .globl ppcDcbf
871ppcDcbf:
872 dcbf r0,r3
873 blr
874
875/*------------------------------------------------------------------------------- */
876/* Function: ppcDcbi */
877/* Description: Data Cache block Invalidate */
878/* Input: r3 = effective address */
879/* Output: none. */
880/*------------------------------------------------------------------------------- */
881 .globl ppcDcbi
882ppcDcbi:
883 dcbi r0,r3
884 blr
885
wdenk13eb2212004-07-09 23:27:13 +0000886/*--------------------------------------------------------------------------
887 * Function: ppcDcbz
888 * Description: Data Cache block zero.
889 * Input: r3 = effective address
890 * Output: none.
891 *-------------------------------------------------------------------------- */
892
893 .globl ppcDcbz
894ppcDcbz:
895 dcbz r0,r3
896 blr
897
wdenk9c53f402003-10-15 23:53:47 +0000898/*------------------------------------------------------------------------------- */
899/* Function: ppcSync */
900/* Description: Processor Synchronize */
901/* Input: none. */
902/* Output: none. */
903/*------------------------------------------------------------------------------- */
904 .globl ppcSync
905ppcSync:
906 sync
907 blr
908
909/*------------------------------------------------------------------------------*/
910
911/*
912 * void relocate_code (addr_sp, gd, addr_moni)
913 *
914 * This "function" does not return, instead it continues in RAM
915 * after relocating the monitor code.
916 *
917 * r3 = dest
918 * r4 = src
919 * r5 = length in bytes
920 * r6 = cachelinesize
921 */
922 .globl relocate_code
923relocate_code:
924 mr r1, r3 /* Set new stack pointer */
925 mr r9, r4 /* Save copy of Init Data pointer */
926 mr r10, r5 /* Save copy of Destination Address */
927
928 mr r3, r5 /* Destination Address */
929 lis r4, CFG_MONITOR_BASE@h /* Source Address */
930 ori r4, r4, CFG_MONITOR_BASE@l
931 lwz r5,GOT(__init_end)
932 sub r5,r5,r4
933 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
934
935 /*
936 * Fix GOT pointer:
937 *
938 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
939 *
940 * Offset:
941 */
942 sub r15, r10, r4
943
944 /* First our own GOT */
945 add r14, r14, r15
946 /* the the one used by the C code */
947 add r30, r30, r15
948
949 /*
950 * Now relocate code
951 */
952
953 cmplw cr1,r3,r4
954 addi r0,r5,3
955 srwi. r0,r0,2
956 beq cr1,4f /* In place copy is not necessary */
957 beq 7f /* Protect against 0 count */
958 mtctr r0
959 bge cr1,2f
960
961 la r8,-4(r4)
962 la r7,-4(r3)
9631: lwzu r0,4(r8)
964 stwu r0,4(r7)
965 bdnz 1b
966 b 4f
967
9682: slwi r0,r0,2
969 add r8,r4,r0
970 add r7,r3,r0
9713: lwzu r0,-4(r8)
972 stwu r0,-4(r7)
973 bdnz 3b
974
975/*
976 * Now flush the cache: note that we must start from a cache aligned
977 * address. Otherwise we might miss one cache line.
978 */
9794: cmpwi r6,0
980 add r5,r3,r5
981 beq 7f /* Always flush prefetch queue in any case */
982 subi r0,r6,1
983 andc r3,r3,r0
984 mr r4,r3
9855: dcbst 0,r4
986 add r4,r4,r6
987 cmplw r4,r5
988 blt 5b
989 sync /* Wait for all dcbst to complete on bus */
990 mr r4,r3
9916: icbi 0,r4
992 add r4,r4,r6
993 cmplw r4,r5
994 blt 6b
9957: sync /* Wait for all icbi to complete on bus */
996 isync
997
Wolfgang Denk29dcbd42005-10-05 00:00:54 +0200998 /*
999 * Re-point the IVPR at RAM
1000 */
1001 mtspr IVPR,r10
1002
wdenk9c53f402003-10-15 23:53:47 +00001003/*
1004 * We are done. Do not return, instead branch to second part of board
1005 * initialization, now running from RAM.
1006 */
1007
1008 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1009 mtlr r0
1010 blr /* NEVER RETURNS! */
1011
1012in_ram:
1013
1014 /*
1015 * Relocation Function, r14 point to got2+0x8000
1016 *
1017 * Adjust got2 pointers, no need to check for 0, this code
1018 * already puts a few entries in the table.
1019 */
1020 li r0,__got2_entries@sectoff@l
1021 la r3,GOT(_GOT2_TABLE_)
1022 lwz r11,GOT(_GOT2_TABLE_)
1023 mtctr r0
1024 sub r11,r3,r11
1025 addi r3,r3,-4
10261: lwzu r0,4(r3)
1027 add r0,r0,r11
1028 stw r0,0(r3)
1029 bdnz 1b
1030
1031 /*
1032 * Now adjust the fixups and the pointers to the fixups
1033 * in case we need to move ourselves again.
1034 */
10352: li r0,__fixup_entries@sectoff@l
1036 lwz r3,GOT(_FIXUP_TABLE_)
1037 cmpwi r0,0
1038 mtctr r0
1039 addi r3,r3,-4
1040 beq 4f
10413: lwzu r4,4(r3)
1042 lwzux r0,r4,r11
1043 add r0,r0,r11
1044 stw r10,0(r3)
1045 stw r0,0(r4)
1046 bdnz 3b
10474:
1048clear_bss:
1049 /*
1050 * Now clear BSS segment
1051 */
1052 lwz r3,GOT(__bss_start)
1053 lwz r4,GOT(_end)
1054
1055 cmplw 0, r3, r4
1056 beq 6f
1057
1058 li r0, 0
10595:
1060 stw r0, 0(r3)
1061 addi r3, r3, 4
1062 cmplw 0, r3, r4
1063 bne 5b
10646:
1065
1066 mr r3, r9 /* Init Data pointer */
1067 mr r4, r10 /* Destination Address */
1068 bl board_init_r
1069
1070 /*
1071 * Copy exception vector code to low memory
1072 *
1073 * r3: dest_addr
1074 * r7: source address, r8: end address, r9: target address
1075 */
wdenkf3da7cc2005-05-13 22:49:36 +00001076 .globl trap_init
wdenk9c53f402003-10-15 23:53:47 +00001077trap_init:
wdenkf3da7cc2005-05-13 22:49:36 +00001078 lwz r7, GOT(_start)
1079 lwz r8, GOT(_end_of_vectors)
wdenk9c53f402003-10-15 23:53:47 +00001080
1081 li r9, 0x100 /* reset vector always at 0x100 */
1082
wdenkf3da7cc2005-05-13 22:49:36 +00001083 cmplw 0, r7, r8
1084 bgelr /* return if r7>=r8 - just in case */
wdenk9c53f402003-10-15 23:53:47 +00001085
wdenkf3da7cc2005-05-13 22:49:36 +00001086 mflr r4 /* save link register */
wdenk9c53f402003-10-15 23:53:47 +000010871:
wdenkf3da7cc2005-05-13 22:49:36 +00001088 lwz r0, 0(r7)
1089 stw r0, 0(r9)
1090 addi r7, r7, 4
1091 addi r9, r9, 4
1092 cmplw 0, r7, r8
1093 bne 1b
wdenk9c53f402003-10-15 23:53:47 +00001094
1095 /*
1096 * relocate `hdlr' and `int_return' entries
1097 */
wdenkf3da7cc2005-05-13 22:49:36 +00001098 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1099 bl trap_reloc
1100 li r7, .L_DataStorage - _start + EXC_OFF_SYS_RESET
1101 bl trap_reloc
1102 li r7, .L_InstStorage - _start + EXC_OFF_SYS_RESET
1103 bl trap_reloc
1104 li r7, .L_ExtInterrupt - _start + EXC_OFF_SYS_RESET
1105 bl trap_reloc
1106 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1107 bl trap_reloc
1108 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1109 bl trap_reloc
1110 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1111 bl trap_reloc
1112 li r7, .L_Decrementer - _start + EXC_OFF_SYS_RESET
1113 bl trap_reloc
1114 li r7, .L_IntervalTimer - _start + EXC_OFF_SYS_RESET
1115 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
wdenk9c53f402003-10-15 23:53:47 +000011162:
wdenkf3da7cc2005-05-13 22:49:36 +00001117 bl trap_reloc
1118 addi r7, r7, 0x100 /* next exception vector */
1119 cmplw 0, r7, r8
1120 blt 2b
wdenk9c53f402003-10-15 23:53:47 +00001121
wdenkf3da7cc2005-05-13 22:49:36 +00001122 lis r7,0x0
1123 mtspr IVPR, r7
wdenk9c53f402003-10-15 23:53:47 +00001124
wdenkf3da7cc2005-05-13 22:49:36 +00001125 mtlr r4 /* restore link register */
wdenk9c53f402003-10-15 23:53:47 +00001126 blr
1127
1128 /*
1129 * Function: relocate entries for one exception vector
1130 */
1131trap_reloc:
wdenkf3da7cc2005-05-13 22:49:36 +00001132 lwz r0, 0(r7) /* hdlr ... */
1133 add r0, r0, r3 /* ... += dest_addr */
1134 stw r0, 0(r7)
wdenk9c53f402003-10-15 23:53:47 +00001135
wdenkf3da7cc2005-05-13 22:49:36 +00001136 lwz r0, 4(r7) /* int_return ... */
1137 add r0, r0, r3 /* ... += dest_addr */
1138 stw r0, 4(r7)
wdenk9c53f402003-10-15 23:53:47 +00001139
1140 blr
1141
1142#ifdef CFG_INIT_RAM_LOCK
1143.globl unlock_ram_in_cache
1144unlock_ram_in_cache:
1145 /* invalidate the INIT_RAM section */
1146 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1147 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1148 li r2,512
1149 mtctr r2
11501: icbi r0, r3
1151 dcbi r0, r3
1152 addi r3, r3, 32
1153 bdnz 1b
wdenkf3da7cc2005-05-13 22:49:36 +00001154 sync /* Wait for all icbi to complete on bus */
wdenk9c53f402003-10-15 23:53:47 +00001155 isync
1156 blr
1157#endif