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