]> git.ipfire.org Git - people/ms/u-boot.git/blame - cpu/mpc85xx/start.S
85xx: Add support for setting IVORs to fixed offset defaults
[people/ms/u-boot.git] / cpu / mpc85xx / start.S
CommitLineData
42d1f039 1/*
61a21e98 2 * Copyright 2004, 2007 Freescale Semiconductor.
42d1f039 3 * Copyright (C) 2003 Motorola,Inc.
42d1f039
WD
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24/* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
25 *
26 * The processor starts at 0xfffffffc and the code is first executed in the
27 * last 4K page(0xfffff000-0xffffffff) in flash/rom.
28 *
29 */
30
31#include <config.h>
32#include <mpc85xx.h>
561858ee 33#include <timestamp.h>
42d1f039
WD
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
61a21e98 49#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
42d1f039
WD
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
61a21e98
AF
83 .section .bootpg,"ax"
84 .globl _start_e500
42d1f039
WD
85
86_start_e500:
97d80fc3 87
61a21e98 88/* clear registers/arrays not reset by hardware */
42d1f039 89
61a21e98
AF
90 /* L1 */
91 li r0,2
92 mtspr L1CSR0,r0 /* invalidate d-cache */
53677ef1 93 mtspr L1CSR1,r0 /* invalidate i-cache */
42d1f039
WD
94
95 mfspr r1,DBSR
96 mtspr DBSR,r1 /* Clear all valid bits */
97
61a21e98
AF
98 /*
99 * Enable L1 Caches early
100 *
101 */
42d1f039 102
61a21e98
AF
103 lis r2,L1CSR0_CPE@H /* enable parity */
104 ori r2,r2,L1CSR0_DCE
105 mtspr L1CSR0,r2 /* enable L1 Dcache */
106 isync
107 mtspr L1CSR1,r2 /* enable L1 Icache */
42d1f039 108 isync
61a21e98 109 msync
42d1f039
WD
110
111 /* Setup interrupt vectors */
343117bf 112 lis r1,TEXT_BASE@h
61a21e98 113 mtspr IVPR,r1
42d1f039 114
343117bf 115 li r1,0x0100
42d1f039 116 mtspr IVOR0,r1 /* 0: Critical input */
343117bf 117 li r1,0x0200
42d1f039 118 mtspr IVOR1,r1 /* 1: Machine check */
343117bf 119 li r1,0x0300
42d1f039 120 mtspr IVOR2,r1 /* 2: Data storage */
343117bf 121 li r1,0x0400
42d1f039
WD
122 mtspr IVOR3,r1 /* 3: Instruction storage */
123 li r1,0x0500
124 mtspr IVOR4,r1 /* 4: External interrupt */
125 li r1,0x0600
126 mtspr IVOR5,r1 /* 5: Alignment */
127 li r1,0x0700
128 mtspr IVOR6,r1 /* 6: Program check */
129 li r1,0x0800
130 mtspr IVOR7,r1 /* 7: floating point unavailable */
343117bf 131 li r1,0x0900
42d1f039
WD
132 mtspr IVOR8,r1 /* 8: System call */
133 /* 9: Auxiliary processor unavailable(unsupported) */
343117bf 134 li r1,0x0a00
42d1f039 135 mtspr IVOR10,r1 /* 10: Decrementer */
343117bf
WD
136 li r1,0x0b00
137 mtspr IVOR11,r1 /* 11: Interval timer */
138 li r1,0x0c00
3e0bc447
WD
139 mtspr IVOR12,r1 /* 12: Watchdog timer */
140 li r1,0x0d00
42d1f039 141 mtspr IVOR13,r1 /* 13: Data TLB error */
343117bf 142 li r1,0x0e00
42d1f039 143 mtspr IVOR14,r1 /* 14: Instruction TLB error */
343117bf 144 li r1,0x0f00
42d1f039
WD
145 mtspr IVOR15,r1 /* 15: Debug */
146
42d1f039 147 /* Clear and set up some registers. */
87163180 148 li r0,0x0000
42d1f039
WD
149 lis r1,0xffff
150 mtspr DEC,r0 /* prevent dec exceptions */
151 mttbl r0 /* prevent fit & wdt exceptions */
152 mttbu r0
153 mtspr TSR,r1 /* clear all timer exception status */
154 mtspr TCR,r0 /* disable all */
155 mtspr ESR,r0 /* clear exception syndrome register */
156 mtspr MCSR,r0 /* machine check syndrome register */
157 mtxer r0 /* clear integer exception register */
42d1f039
WD
158
159 /* Enable Time Base and Select Time Base Clock */
0ac6f8b7 160 lis r0,HID0_EMCP@h /* Enable machine check */
d9b94f28 161#if defined(CONFIG_ENABLE_36BIT_PHYS)
87163180 162 ori r0,r0,HID0_ENMAS7@l /* Enable MAS7 */
d9b94f28 163#endif
1b3e4044 164#ifndef CONFIG_E500MC
87163180 165 ori r0,r0,HID0_TBEN@l /* Enable Timebase */
1b3e4044 166#endif
42d1f039 167 mtspr HID0,r0
42d1f039 168
0f060c3b 169#ifndef CONFIG_E500MC
61a21e98 170 li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
42d1f039 171 mtspr HID1,r0
0f060c3b 172#endif
42d1f039
WD
173
174 /* Enable Branch Prediction */
175#if defined(CONFIG_BTB)
176 li r0,0x201 /* BBFI = 1, BPEN = 1 */
177 mtspr BUCSR,r0
42d1f039
WD
178#endif
179
6d0f6bcf 180#if defined(CONFIG_SYS_INIT_DBCR)
42d1f039
WD
181 lis r1,0xffff
182 ori r1,r1,0xffff
0ac6f8b7 183 mtspr DBSR,r1 /* Clear all status bits */
6d0f6bcf
JCPV
184 lis r0,CONFIG_SYS_INIT_DBCR@h /* DBCR0[IDM] must be set */
185 ori r0,r0,CONFIG_SYS_INIT_DBCR@l
0ac6f8b7 186 mtspr DBCR0,r0
42d1f039
WD
187#endif
188
22b6dbc1
HW
189#ifdef CONFIG_MPC8569
190#define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
191#define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
192
193 /* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
194 * use address space which is more than 12bits, and it must be done in
195 * the 4K boot page. So we set this bit here.
196 */
197
198 /* create a temp mapping TLB0[0] for LBCR */
199 lis r6,FSL_BOOKE_MAS0(0, 0, 0)@h
200 ori r6,r6,FSL_BOOKE_MAS0(0, 0, 0)@l
201
202 lis r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h
203 ori r7,r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@l
204
205 lis r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@h
206 ori r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@l
207
208 lis r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
209 (MAS3_SX|MAS3_SW|MAS3_SR))@h
210 ori r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
211 (MAS3_SX|MAS3_SW|MAS3_SR))@l
212
213 mtspr MAS0,r6
214 mtspr MAS1,r7
215 mtspr MAS2,r8
216 mtspr MAS3,r9
217 isync
218 msync
219 tlbwe
220
221 /* Set LBCR register */
222 lis r4,CONFIG_SYS_LBCR_ADDR@h
223 ori r4,r4,CONFIG_SYS_LBCR_ADDR@l
224
225 lis r5,CONFIG_SYS_LBC_LBCR@h
226 ori r5,r5,CONFIG_SYS_LBC_LBCR@l
227 stw r5,0(r4)
228 isync
229
230 /* invalidate this temp TLB */
231 lis r4,CONFIG_SYS_LBC_ADDR@h
232 ori r4,r4,CONFIG_SYS_LBC_ADDR@l
233 tlbivax 0,r4
234 isync
235
236#endif /* CONFIG_MPC8569 */
237
f51f07eb 238 /* create a temp mapping in AS=1 to the 4M boot window */
87163180
KG
239 lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
240 ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
241
f51f07eb
DL
242 lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
243 ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
87163180 244
f51f07eb
DL
245 lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
246 ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
87163180 247
f51f07eb
DL
248 /* The 85xx has the default boot window 0xff800000 - 0xffffffff */
249 lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
250 ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
87163180
KG
251
252 mtspr MAS0,r6
253 mtspr MAS1,r7
254 mtspr MAS2,r8
255 mtspr MAS3,r9
256 isync
257 msync
258 tlbwe
259
260 /* create a temp mapping in AS=1 to the stack */
261 lis r6,FSL_BOOKE_MAS0(1, 14, 0)@h
262 ori r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
263
264 lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
265 ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
266
6d0f6bcf
JCPV
267 lis r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@h
268 ori r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@l
87163180 269
6d0f6bcf
JCPV
270 lis r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
271 ori r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
87163180
KG
272
273 mtspr MAS0,r6
274 mtspr MAS1,r7
275 mtspr MAS2,r8
276 mtspr MAS3,r9
277 isync
278 msync
279 tlbwe
280
281 lis r6,MSR_CE|MSR_ME|MSR_DE|MSR_IS|MSR_DS@h
282 ori r6,r6,MSR_CE|MSR_ME|MSR_DE|MSR_IS|MSR_DS@l
283 lis r7,switch_as@h
284 ori r7,r7,switch_as@l
285
286 mtspr SPRN_SRR0,r7
287 mtspr SPRN_SRR1,r6
288 rfi
289
290switch_as:
3db0bef5
KG
291/* L1 DCache is used for initial RAM */
292
293 /* Allocate Initial RAM in data cache.
294 */
6d0f6bcf
JCPV
295 lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
296 ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
b009f3ec
KG
297 mfspr r2, L1CFG0
298 andi. r2, r2, 0x1ff
299 /* cache size * 1024 / (2 * L1 line size) */
300 slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT)
3db0bef5
KG
301 mtctr r2
302 li r0,0
3031:
304 dcbz r0,r3
305 dcbtls 0,r0,r3
6d0f6bcf 306 addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
3db0bef5
KG
307 bdnz 1b
308
61a21e98 309 /* Jump out the last 4K page and continue to 'normal' start */
6d0f6bcf 310#ifdef CONFIG_SYS_RAMBOOT
61a21e98 311 b _start_cont
3db0bef5
KG
312#else
313 /* Calculate absolute address in FLASH and jump there */
314 /*--------------------------------------------------------------*/
6d0f6bcf
JCPV
315 lis r3,CONFIG_SYS_MONITOR_BASE@h
316 ori r3,r3,CONFIG_SYS_MONITOR_BASE@l
3db0bef5
KG
317 addi r3,r3,_start_cont - _start + _START_OFFSET
318 mtlr r3
1e701e70 319 blr
3db0bef5 320#endif
61a21e98 321
61a21e98
AF
322 .text
323 .globl _start
324_start:
325 .long 0x27051956 /* U-BOOT Magic Number */
326 .globl version_string
327version_string:
328 .ascii U_BOOT_VERSION
561858ee 329 .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
61a21e98
AF
330 .ascii CONFIG_IDENT_STRING, "\0"
331
332 .align 4
333 .globl _start_cont
334_start_cont:
42d1f039 335 /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
6d0f6bcf
JCPV
336 lis r1,CONFIG_SYS_INIT_RAM_ADDR@h
337 ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
42d1f039
WD
338
339 li r0,0
340 stwu r0,-4(r1)
341 stwu r0,-4(r1) /* Terminate call chain */
342
343 stwu r1,-8(r1) /* Save back chain and move SP */
344 lis r0,RESET_VECTOR@h /* Address of reset vector */
61a21e98 345 ori r0,r0,RESET_VECTOR@l
42d1f039
WD
346 stwu r1,-8(r1) /* Save back chain and move SP */
347 stw r0,+12(r1) /* Save return addr (underflow vect) */
348
349 GET_GOT
87163180
KG
350 bl cpu_init_early_f
351
352 /* switch back to AS = 0 */
353 lis r3,(MSR_CE|MSR_ME|MSR_DE)@h
354 ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
355 mtmsr r3
356 isync
357
42d1f039 358 bl cpu_init_f
42d1f039 359 bl board_init_f
0ac6f8b7 360 isync
42d1f039 361
61a21e98 362 . = EXC_OFF_SYS_RESET
42d1f039
WD
363 .globl _start_of_vectors
364_start_of_vectors:
61a21e98 365
42d1f039 366/* Critical input. */
61a21e98
AF
367 CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
368
369/* Machine check */
370 MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
42d1f039
WD
371
372/* Data Storage exception. */
373 STD_EXCEPTION(0x0300, DataStorage, UnknownException)
374
375/* Instruction Storage exception. */
376 STD_EXCEPTION(0x0400, InstStorage, UnknownException)
377
378/* External Interrupt exception. */
61a21e98 379 STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
42d1f039
WD
380
381/* Alignment exception. */
382 . = 0x0600
383Alignment:
02032e8f 384 EXCEPTION_PROLOG(SRR0, SRR1)
42d1f039
WD
385 mfspr r4,DAR
386 stw r4,_DAR(r21)
387 mfspr r5,DSISR
388 stw r5,_DSISR(r21)
389 addi r3,r1,STACK_FRAME_OVERHEAD
390 li r20,MSR_KERNEL
391 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
392 lwz r6,GOT(transfer_to_handler)
393 mtlr r6
394 blrl
395.L_Alignment:
61a21e98
AF
396 .long AlignmentException - _start + _START_OFFSET
397 .long int_return - _start + _START_OFFSET
42d1f039
WD
398
399/* Program check exception */
400 . = 0x0700
401ProgramCheck:
02032e8f 402 EXCEPTION_PROLOG(SRR0, SRR1)
42d1f039
WD
403 addi r3,r1,STACK_FRAME_OVERHEAD
404 li r20,MSR_KERNEL
405 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
406 lwz r6,GOT(transfer_to_handler)
407 mtlr r6
408 blrl
409.L_ProgramCheck:
61a21e98
AF
410 .long ProgramCheckException - _start + _START_OFFSET
411 .long int_return - _start + _START_OFFSET
42d1f039
WD
412
413 /* No FPU on MPC85xx. This exception is not supposed to happen.
414 */
415 STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
42d1f039 416
343117bf 417 . = 0x0900
42d1f039
WD
418/*
419 * r0 - SYSCALL number
420 * r3-... arguments
421 */
422SystemCall:
61a21e98
AF
423 addis r11,r0,0 /* get functions table addr */
424 ori r11,r11,0 /* Note: this code is patched in trap_init */
425 addis r12,r0,0 /* get number of functions */
343117bf
WD
426 ori r12,r12,0
427
61a21e98 428 cmplw 0,r0,r12
343117bf
WD
429 bge 1f
430
61a21e98 431 rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
343117bf
WD
432 add r11,r11,r0
433 lwz r11,0(r11)
434
61a21e98 435 li r20,0xd00-4 /* Get stack pointer */
343117bf 436 lwz r12,0(r20)
61a21e98 437 subi r12,r12,12 /* Adjust stack pointer */
343117bf 438 li r0,0xc00+_end_back-SystemCall
61a21e98 439 cmplw 0,r0,r12 /* Check stack overflow */
343117bf
WD
440 bgt 1f
441 stw r12,0(r20)
442
443 mflr r0
444 stw r0,0(r12)
445 mfspr r0,SRR0
446 stw r0,4(r12)
447 mfspr r0,SRR1
448 stw r0,8(r12)
449
450 li r12,0xc00+_back-SystemCall
451 mtlr r12
452 mtspr SRR0,r11
453
4541: SYNC
42d1f039
WD
455 rfi
456_back:
457
343117bf
WD
458 mfmsr r11 /* Disable interrupts */
459 li r12,0
460 ori r12,r12,MSR_EE
461 andc r11,r11,r12
462 SYNC /* Some chip revs need this... */
463 mtmsr r11
42d1f039
WD
464 SYNC
465
343117bf
WD
466 li r12,0xd00-4 /* restore regs */
467 lwz r12,0(r12)
42d1f039 468
343117bf
WD
469 lwz r11,0(r12)
470 mtlr r11
471 lwz r11,4(r12)
472 mtspr SRR0,r11
473 lwz r11,8(r12)
474 mtspr SRR1,r11
42d1f039 475
343117bf
WD
476 addi r12,r12,12 /* Adjust stack pointer */
477 li r20,0xd00-4
478 stw r12,0(r20)
42d1f039
WD
479
480 SYNC
481 rfi
482_end_back:
483
343117bf
WD
484 STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
485 STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
486 STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
42d1f039 487
343117bf
WD
488 STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
489 STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
42d1f039 490
343117bf 491 CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
42d1f039 492
343117bf 493 .globl _end_of_vectors
42d1f039
WD
494_end_of_vectors:
495
496
61a21e98 497 . = . + (0x100 - ( . & 0xff )) /* align for debug */
42d1f039
WD
498
499/*
500 * This code finishes saving the registers to the exception frame
501 * and jumps to the appropriate handler for the exception.
502 * Register r21 is pointer into trap frame, r1 has new stack pointer.
503 */
504 .globl transfer_to_handler
505transfer_to_handler:
506 stw r22,_NIP(r21)
507 lis r22,MSR_POW@h
508 andc r23,r23,r22
509 stw r23,_MSR(r21)
510 SAVE_GPR(7, r21)
511 SAVE_4GPRS(8, r21)
512 SAVE_8GPRS(12, r21)
513 SAVE_8GPRS(24, r21)
514
515 mflr r23
516 andi. r24,r23,0x3f00 /* get vector offset */
517 stw r24,TRAP(r21)
518 li r22,0
519 stw r22,RESULT(r21)
520 mtspr SPRG2,r22 /* r1 is now kernel sp */
521
522 lwz r24,0(r23) /* virtual address of handler */
523 lwz r23,4(r23) /* where to go when done */
524 mtspr SRR0,r24
525 mtspr SRR1,r20
526 mtlr r23
527 SYNC
528 rfi /* jump to handler, enable MMU */
529
530int_return:
531 mfmsr r28 /* Disable interrupts */
532 li r4,0
533 ori r4,r4,MSR_EE
534 andc r28,r28,r4
535 SYNC /* Some chip revs need this... */
536 mtmsr r28
537 SYNC
538 lwz r2,_CTR(r1)
539 lwz r0,_LINK(r1)
540 mtctr r2
541 mtlr r0
542 lwz r2,_XER(r1)
543 lwz r0,_CCR(r1)
544 mtspr XER,r2
545 mtcrf 0xFF,r0
546 REST_10GPRS(3, r1)
547 REST_10GPRS(13, r1)
548 REST_8GPRS(23, r1)
549 REST_GPR(31, r1)
550 lwz r2,_NIP(r1) /* Restore environment */
551 lwz r0,_MSR(r1)
552 mtspr SRR0,r2
553 mtspr SRR1,r0
554 lwz r0,GPR0(r1)
555 lwz r2,GPR2(r1)
556 lwz r1,GPR1(r1)
557 SYNC
558 rfi
559
560crit_return:
561 mfmsr r28 /* Disable interrupts */
562 li r4,0
563 ori r4,r4,MSR_EE
564 andc r28,r28,r4
565 SYNC /* Some chip revs need this... */
566 mtmsr r28
567 SYNC
568 lwz r2,_CTR(r1)
569 lwz r0,_LINK(r1)
570 mtctr r2
571 mtlr r0
572 lwz r2,_XER(r1)
573 lwz r0,_CCR(r1)
574 mtspr XER,r2
575 mtcrf 0xFF,r0
576 REST_10GPRS(3, r1)
577 REST_10GPRS(13, r1)
578 REST_8GPRS(23, r1)
579 REST_GPR(31, r1)
580 lwz r2,_NIP(r1) /* Restore environment */
581 lwz r0,_MSR(r1)
61a21e98
AF
582 mtspr SPRN_CSRR0,r2
583 mtspr SPRN_CSRR1,r0
42d1f039
WD
584 lwz r0,GPR0(r1)
585 lwz r2,GPR2(r1)
586 lwz r1,GPR1(r1)
587 SYNC
588 rfci
589
61a21e98
AF
590mck_return:
591 mfmsr r28 /* Disable interrupts */
592 li r4,0
593 ori r4,r4,MSR_EE
594 andc r28,r28,r4
595 SYNC /* Some chip revs need this... */
596 mtmsr r28
597 SYNC
598 lwz r2,_CTR(r1)
599 lwz r0,_LINK(r1)
600 mtctr r2
601 mtlr r0
602 lwz r2,_XER(r1)
603 lwz r0,_CCR(r1)
604 mtspr XER,r2
605 mtcrf 0xFF,r0
606 REST_10GPRS(3, r1)
607 REST_10GPRS(13, r1)
608 REST_8GPRS(23, r1)
609 REST_GPR(31, r1)
610 lwz r2,_NIP(r1) /* Restore environment */
611 lwz r0,_MSR(r1)
612 mtspr SPRN_MCSRR0,r2
613 mtspr SPRN_MCSRR1,r0
614 lwz r0,GPR0(r1)
615 lwz r2,GPR2(r1)
616 lwz r1,GPR1(r1)
617 SYNC
618 rfmci
619
42d1f039
WD
620/* Cache functions.
621*/
54e091d3 622.globl invalidate_icache
42d1f039
WD
623invalidate_icache:
624 mfspr r0,L1CSR1
61a21e98
AF
625 ori r0,r0,L1CSR1_ICFI
626 msync
627 isync
42d1f039
WD
628 mtspr L1CSR1,r0
629 isync
61a21e98 630 blr /* entire I cache */
42d1f039 631
54e091d3 632.globl invalidate_dcache
42d1f039
WD
633invalidate_dcache:
634 mfspr r0,L1CSR0
61a21e98 635 ori r0,r0,L1CSR0_DCFI
42d1f039
WD
636 msync
637 isync
638 mtspr L1CSR0,r0
639 isync
640 blr
641
642 .globl icache_enable
643icache_enable:
644 mflr r8
645 bl invalidate_icache
646 mtlr r8
647 isync
648 mfspr r4,L1CSR1
649 ori r4,r4,0x0001
650 oris r4,r4,0x0001
651 mtspr L1CSR1,r4
652 isync
653 blr
654
655 .globl icache_disable
656icache_disable:
657 mfspr r0,L1CSR1
61a21e98
AF
658 lis r3,0
659 ori r3,r3,L1CSR1_ICE
660 andc r0,r0,r3
42d1f039
WD
661 mtspr L1CSR1,r0
662 isync
663 blr
664
665 .globl icache_status
666icache_status:
667 mfspr r3,L1CSR1
61a21e98 668 andi. r3,r3,L1CSR1_ICE
42d1f039
WD
669 blr
670
671 .globl dcache_enable
672dcache_enable:
673 mflr r8
674 bl invalidate_dcache
675 mtlr r8
676 isync
677 mfspr r0,L1CSR0
678 ori r0,r0,0x0001
679 oris r0,r0,0x0001
680 msync
681 isync
682 mtspr L1CSR0,r0
683 isync
684 blr
685
686 .globl dcache_disable
687dcache_disable:
61a21e98
AF
688 mfspr r3,L1CSR0
689 lis r4,0
690 ori r4,r4,L1CSR0_DCE
691 andc r3,r3,r4
42d1f039
WD
692 mtspr L1CSR0,r0
693 isync
694 blr
695
696 .globl dcache_status
697dcache_status:
698 mfspr r3,L1CSR0
61a21e98 699 andi. r3,r3,L1CSR0_DCE
42d1f039
WD
700 blr
701
702 .globl get_pir
703get_pir:
61a21e98 704 mfspr r3,PIR
42d1f039
WD
705 blr
706
707 .globl get_pvr
708get_pvr:
61a21e98 709 mfspr r3,PVR
42d1f039
WD
710 blr
711
97d80fc3
WD
712 .globl get_svr
713get_svr:
61a21e98 714 mfspr r3,SVR
97d80fc3
WD
715 blr
716
42d1f039
WD
717 .globl wr_tcr
718wr_tcr:
61a21e98 719 mtspr TCR,r3
42d1f039
WD
720 blr
721
722/*------------------------------------------------------------------------------- */
723/* Function: in8 */
724/* Description: Input 8 bits */
725/*------------------------------------------------------------------------------- */
726 .globl in8
727in8:
728 lbz r3,0x0000(r3)
729 blr
730
731/*------------------------------------------------------------------------------- */
732/* Function: out8 */
733/* Description: Output 8 bits */
734/*------------------------------------------------------------------------------- */
735 .globl out8
736out8:
737 stb r4,0x0000(r3)
1487adbd 738 sync
42d1f039
WD
739 blr
740
741/*------------------------------------------------------------------------------- */
742/* Function: out16 */
743/* Description: Output 16 bits */
744/*------------------------------------------------------------------------------- */
745 .globl out16
746out16:
747 sth r4,0x0000(r3)
1487adbd 748 sync
42d1f039
WD
749 blr
750
751/*------------------------------------------------------------------------------- */
752/* Function: out16r */
753/* Description: Byte reverse and output 16 bits */
754/*------------------------------------------------------------------------------- */
755 .globl out16r
756out16r:
757 sthbrx r4,r0,r3
1487adbd 758 sync
42d1f039
WD
759 blr
760
761/*------------------------------------------------------------------------------- */
762/* Function: out32 */
763/* Description: Output 32 bits */
764/*------------------------------------------------------------------------------- */
765 .globl out32
766out32:
767 stw r4,0x0000(r3)
1487adbd 768 sync
42d1f039
WD
769 blr
770
771/*------------------------------------------------------------------------------- */
772/* Function: out32r */
773/* Description: Byte reverse and output 32 bits */
774/*------------------------------------------------------------------------------- */
775 .globl out32r
776out32r:
777 stwbrx r4,r0,r3
1487adbd 778 sync
42d1f039
WD
779 blr
780
781/*------------------------------------------------------------------------------- */
782/* Function: in16 */
783/* Description: Input 16 bits */
784/*------------------------------------------------------------------------------- */
785 .globl in16
786in16:
787 lhz r3,0x0000(r3)
788 blr
789
790/*------------------------------------------------------------------------------- */
791/* Function: in16r */
792/* Description: Input 16 bits and byte reverse */
793/*------------------------------------------------------------------------------- */
794 .globl in16r
795in16r:
796 lhbrx r3,r0,r3
797 blr
798
799/*------------------------------------------------------------------------------- */
800/* Function: in32 */
801/* Description: Input 32 bits */
802/*------------------------------------------------------------------------------- */
803 .globl in32
804in32:
805 lwz 3,0x0000(3)
806 blr
807
808/*------------------------------------------------------------------------------- */
809/* Function: in32r */
810/* Description: Input 32 bits and byte reverse */
811/*------------------------------------------------------------------------------- */
812 .globl in32r
813in32r:
814 lwbrx r3,r0,r3
815 blr
816
42d1f039
WD
817/*------------------------------------------------------------------------------*/
818
819/*
820 * void relocate_code (addr_sp, gd, addr_moni)
821 *
822 * This "function" does not return, instead it continues in RAM
823 * after relocating the monitor code.
824 *
825 * r3 = dest
826 * r4 = src
827 * r5 = length in bytes
828 * r6 = cachelinesize
829 */
830 .globl relocate_code
831relocate_code:
61a21e98
AF
832 mr r1,r3 /* Set new stack pointer */
833 mr r9,r4 /* Save copy of Init Data pointer */
834 mr r10,r5 /* Save copy of Destination Address */
42d1f039 835
61a21e98 836 mr r3,r5 /* Destination Address */
6d0f6bcf
JCPV
837 lis r4,CONFIG_SYS_MONITOR_BASE@h /* Source Address */
838 ori r4,r4,CONFIG_SYS_MONITOR_BASE@l
42d1f039
WD
839 lwz r5,GOT(__init_end)
840 sub r5,r5,r4
6d0f6bcf 841 li r6,CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
42d1f039
WD
842
843 /*
844 * Fix GOT pointer:
845 *
6d0f6bcf 846 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
42d1f039
WD
847 *
848 * Offset:
849 */
61a21e98 850 sub r15,r10,r4
42d1f039
WD
851
852 /* First our own GOT */
61a21e98 853 add r14,r14,r15
42d1f039 854 /* the the one used by the C code */
61a21e98 855 add r30,r30,r15
42d1f039
WD
856
857 /*
858 * Now relocate code
859 */
860
861 cmplw cr1,r3,r4
862 addi r0,r5,3
863 srwi. r0,r0,2
864 beq cr1,4f /* In place copy is not necessary */
865 beq 7f /* Protect against 0 count */
866 mtctr r0
867 bge cr1,2f
868
869 la r8,-4(r4)
870 la r7,-4(r3)
8711: lwzu r0,4(r8)
872 stwu r0,4(r7)
873 bdnz 1b
874 b 4f
875
8762: slwi r0,r0,2
877 add r8,r4,r0
878 add r7,r3,r0
8793: lwzu r0,-4(r8)
880 stwu r0,-4(r7)
881 bdnz 3b
882
883/*
884 * Now flush the cache: note that we must start from a cache aligned
885 * address. Otherwise we might miss one cache line.
886 */
8874: cmpwi r6,0
888 add r5,r3,r5
889 beq 7f /* Always flush prefetch queue in any case */
890 subi r0,r6,1
891 andc r3,r3,r0
892 mr r4,r3
8935: dcbst 0,r4
894 add r4,r4,r6
895 cmplw r4,r5
896 blt 5b
897 sync /* Wait for all dcbst to complete on bus */
898 mr r4,r3
8996: icbi 0,r4
900 add r4,r4,r6
901 cmplw r4,r5
902 blt 6b
9037: sync /* Wait for all icbi to complete on bus */
904 isync
905
7d314992
WD
906 /*
907 * Re-point the IVPR at RAM
908 */
909 mtspr IVPR,r10
99b0d285 910
42d1f039
WD
911/*
912 * We are done. Do not return, instead branch to second part of board
913 * initialization, now running from RAM.
914 */
915
61a21e98 916 addi r0,r10,in_ram - _start + _START_OFFSET
42d1f039
WD
917 mtlr r0
918 blr /* NEVER RETURNS! */
61a21e98 919 .globl in_ram
42d1f039
WD
920in_ram:
921
922 /*
923 * Relocation Function, r14 point to got2+0x8000
924 *
925 * Adjust got2 pointers, no need to check for 0, this code
926 * already puts a few entries in the table.
927 */
928 li r0,__got2_entries@sectoff@l
929 la r3,GOT(_GOT2_TABLE_)
930 lwz r11,GOT(_GOT2_TABLE_)
931 mtctr r0
932 sub r11,r3,r11
933 addi r3,r3,-4
9341: lwzu r0,4(r3)
935 add r0,r0,r11
936 stw r0,0(r3)
937 bdnz 1b
938
939 /*
940 * Now adjust the fixups and the pointers to the fixups
941 * in case we need to move ourselves again.
942 */
9432: li r0,__fixup_entries@sectoff@l
944 lwz r3,GOT(_FIXUP_TABLE_)
945 cmpwi r0,0
946 mtctr r0
947 addi r3,r3,-4
948 beq 4f
9493: lwzu r4,4(r3)
950 lwzux r0,r4,r11
951 add r0,r0,r11
952 stw r10,0(r3)
953 stw r0,0(r4)
954 bdnz 3b
9554:
956clear_bss:
957 /*
958 * Now clear BSS segment
959 */
960 lwz r3,GOT(__bss_start)
961 lwz r4,GOT(_end)
962
61a21e98 963 cmplw 0,r3,r4
42d1f039
WD
964 beq 6f
965
61a21e98 966 li r0,0
42d1f039 9675:
61a21e98
AF
968 stw r0,0(r3)
969 addi r3,r3,4
970 cmplw 0,r3,r4
42d1f039
WD
971 bne 5b
9726:
973
61a21e98
AF
974 mr r3,r9 /* Init Data pointer */
975 mr r4,r10 /* Destination Address */
42d1f039
WD
976 bl board_init_r
977
978 /*
979 * Copy exception vector code to low memory
980 *
981 * r3: dest_addr
982 * r7: source address, r8: end address, r9: target address
983 */
343117bf 984 .globl trap_init
42d1f039 985trap_init:
61a21e98
AF
986 lwz r7,GOT(_start_of_vectors)
987 lwz r8,GOT(_end_of_vectors)
42d1f039 988
61a21e98 989 li r9,0x100 /* reset vector always at 0x100 */
42d1f039 990
61a21e98 991 cmplw 0,r7,r8
343117bf 992 bgelr /* return if r7>=r8 - just in case */
42d1f039 993
343117bf 994 mflr r4 /* save link register */
42d1f039 9951:
61a21e98
AF
996 lwz r0,0(r7)
997 stw r0,0(r9)
998 addi r7,r7,4
999 addi r9,r9,4
1000 cmplw 0,r7,r8
343117bf 1001 bne 1b
42d1f039
WD
1002
1003 /*
1004 * relocate `hdlr' and `int_return' entries
1005 */
61a21e98 1006 li r7,.L_CriticalInput - _start + _START_OFFSET
343117bf 1007 bl trap_reloc
61a21e98 1008 li r7,.L_MachineCheck - _start + _START_OFFSET
343117bf 1009 bl trap_reloc
61a21e98 1010 li r7,.L_DataStorage - _start + _START_OFFSET
343117bf 1011 bl trap_reloc
61a21e98 1012 li r7,.L_InstStorage - _start + _START_OFFSET
343117bf 1013 bl trap_reloc
61a21e98 1014 li r7,.L_ExtInterrupt - _start + _START_OFFSET
343117bf 1015 bl trap_reloc
61a21e98 1016 li r7,.L_Alignment - _start + _START_OFFSET
343117bf 1017 bl trap_reloc
61a21e98 1018 li r7,.L_ProgramCheck - _start + _START_OFFSET
343117bf 1019 bl trap_reloc
61a21e98 1020 li r7,.L_FPUnavailable - _start + _START_OFFSET
343117bf 1021 bl trap_reloc
61a21e98
AF
1022 li r7,.L_Decrementer - _start + _START_OFFSET
1023 bl trap_reloc
1024 li r7,.L_IntervalTimer - _start + _START_OFFSET
1025 li r8,_end_of_vectors - _start + _START_OFFSET
42d1f039 10262:
343117bf 1027 bl trap_reloc
61a21e98
AF
1028 addi r7,r7,0x100 /* next exception vector */
1029 cmplw 0,r7,r8
343117bf
WD
1030 blt 2b
1031
1032 lis r7,0x0
61a21e98 1033 mtspr IVPR,r7
42d1f039 1034
343117bf 1035 mtlr r4 /* restore link register */
42d1f039
WD
1036 blr
1037
1038 /*
1039 * Function: relocate entries for one exception vector
1040 */
1041trap_reloc:
61a21e98
AF
1042 lwz r0,0(r7) /* hdlr ... */
1043 add r0,r0,r3 /* ... += dest_addr */
1044 stw r0,0(r7)
42d1f039 1045
61a21e98
AF
1046 lwz r0,4(r7) /* int_return ... */
1047 add r0,r0,r3 /* ... += dest_addr */
1048 stw r0,4(r7)
42d1f039
WD
1049
1050 blr
1051
42d1f039
WD
1052.globl unlock_ram_in_cache
1053unlock_ram_in_cache:
1054 /* invalidate the INIT_RAM section */
a38a5b6e
KG
1055 lis r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
1056 ori r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
b009f3ec
KG
1057 mfspr r4,L1CFG0
1058 andi. r4,r4,0x1ff
1059 slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT)
61a21e98 1060 mtctr r4
2b22fa4b 10611: dcbi r0,r3
6d0f6bcf 1062 addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
42d1f039 1063 bdnz 1b
2b22fa4b 1064 sync
21fae8b2
AF
1065
1066 /* Invalidate the TLB entries for the cache */
6d0f6bcf
JCPV
1067 lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
1068 ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
21fae8b2
AF
1069 tlbivax 0,r3
1070 addi r3,r3,0x1000
1071 tlbivax 0,r3
1072 addi r3,r3,0x1000
1073 tlbivax 0,r3
1074 addi r3,r3,0x1000
1075 tlbivax 0,r3
42d1f039
WD
1076 isync
1077 blr
54e091d3
KG
1078
1079.globl flush_dcache
1080flush_dcache:
1081 mfspr r3,SPRN_L1CFG0
1082
1083 rlwinm r5,r3,9,3 /* Extract cache block size */
1084 twlgti r5,1 /* Only 32 and 64 byte cache blocks
1085 * are currently defined.
1086 */
1087 li r4,32
1088 subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
1089 * log2(number of ways)
1090 */
1091 slw r5,r4,r5 /* r5 = cache block size */
1092
1093 rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
1094 mulli r7,r7,13 /* An 8-way cache will require 13
1095 * loads per set.
1096 */
1097 slw r7,r7,r6
1098
1099 /* save off HID0 and set DCFA */
1100 mfspr r8,SPRN_HID0
1101 ori r9,r8,HID0_DCFA@l
1102 mtspr SPRN_HID0,r9
1103 isync
1104
1105 lis r4,0
1106 mtctr r7
1107
11081: lwz r3,0(r4) /* Load... */
1109 add r4,r4,r5
1110 bdnz 1b
1111
1112 msync
1113 lis r4,0
1114 mtctr r7
1115
11161: dcbf 0,r4 /* ...and flush. */
1117 add r4,r4,r5
1118 bdnz 1b
1119
1120 /* restore HID0 */
1121 mtspr SPRN_HID0,r8
1122 isync
1123
1124 blr
26f4cdba
KG
1125
1126.globl setup_ivors
1127setup_ivors:
1128
1129#include "fixed_ivor.S"
1130 blr