blob: 54793f052361763179b4c7de7c7296f0524a79f6 [file] [log] [blame]
wdenk21136db2003-07-16 21:53:01 +00001/*
2 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
3 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4 * Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
5 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
wdenk21136db2003-07-16 21:53:01 +00007 */
8
9/*
10 * U-Boot - Startup Code for MPC5xxx CPUs
11 */
Wolfgang Denk0191e472010-10-26 14:34:52 +020012#include <asm-offsets.h>
wdenk21136db2003-07-16 21:53:01 +000013#include <config.h>
14#include <mpc5xxx.h>
15#include <version.h>
16
wdenk21136db2003-07-16 21:53:01 +000017#include <ppc_asm.tmpl>
18#include <ppc_defs.h>
19
20#include <asm/cache.h>
21#include <asm/mmu.h>
Peter Tyser3a1362d2010-10-14 23:33:24 -050022#include <asm/u-boot.h>
wdenk21136db2003-07-16 21:53:01 +000023
wdenk21136db2003-07-16 21:53:01 +000024/* We don't want the MMU yet.
25*/
26#undef MSR_KERNEL
27/* Floating Point enable, Machine Check and Recoverable Interr. */
28#ifdef DEBUG
29#define MSR_KERNEL (MSR_FP|MSR_RI)
30#else
31#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
32#endif
33
Stefan Roese50b5ac02012-08-16 17:53:18 +020034#ifndef CONFIG_SPL_BUILD
wdenk21136db2003-07-16 21:53:01 +000035/*
36 * Set up GOT: Global Offset Table
37 *
Joakim Tjernlund3fbaa4d2010-01-19 14:41:56 +010038 * Use r12 to access the GOT
wdenk21136db2003-07-16 21:53:01 +000039 */
40 START_GOT
41 GOT_ENTRY(_GOT2_TABLE_)
42 GOT_ENTRY(_FIXUP_TABLE_)
43
44 GOT_ENTRY(_start)
45 GOT_ENTRY(_start_of_vectors)
46 GOT_ENTRY(_end_of_vectors)
47 GOT_ENTRY(transfer_to_handler)
48
49 GOT_ENTRY(__init_end)
Simon Glassed70c8f2013-03-14 06:54:53 +000050 GOT_ENTRY(__bss_end)
wdenk21136db2003-07-16 21:53:01 +000051 GOT_ENTRY(__bss_start)
52 END_GOT
Stefan Roese50b5ac02012-08-16 17:53:18 +020053#endif
wdenk21136db2003-07-16 21:53:01 +000054
55/*
56 * Version string
57 */
58 .data
59 .globl version_string
60version_string:
Andreas Bießmann61d01952011-07-18 20:24:04 +020061 .ascii U_BOOT_VERSION_STRING, "\0"
wdenk21136db2003-07-16 21:53:01 +000062
63/*
64 * Exception vectors
65 */
66 .text
67 . = EXC_OFF_SYS_RESET
68 .globl _start
69_start:
Stefan Roese50b5ac02012-08-16 17:53:18 +020070
71#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
72 /*
73 * This is the entry of the real U-Boot from a board port
74 * that supports SPL booting on the MPC5200. We only need
75 * to call board_init_f() here. Everything else has already
76 * been done in the SPL u-boot version.
77 */
78 GET_GOT /* initialize GOT access */
Stefan Roese70a96f92014-11-19 09:37:48 +010079
80 /*
81 * The GD (global data) struct needs to get cleared. Lets do
82 * this by calling memset().
83 * This function is called when the platform is build with SPL
84 * support from the main (full-blown) U-Boot. And the GD needs
85 * to get cleared (again) so that the following generic
86 * board support code, defined via CONFIG_SYS_GENERIC_BOARD,
87 * initializes all variables correctly.
88 */
89 mr r3, r2 /* parameter 1: GD pointer */
90 li r4,0 /* parameter 2: value to fill */
91 li r5,GD_SIZE /* parameter 3: count */
92 bl memset
93
Heiko Schocherba97b982015-11-25 09:46:19 +010094 li r3, 0 /* parameter 1: bootflag */
Stefan Roese50b5ac02012-08-16 17:53:18 +020095 bl board_init_f /* run 1st part of board init code (in Flash)*/
96 /* NOTREACHED - board_init_f() does not return */
97#else
wdenk21136db2003-07-16 21:53:01 +000098 mfmsr r5 /* save msr contents */
99
wdenke44b9112004-04-18 23:32:11 +0000100 /* Move CSBoot and adjust instruction pointer */
101 /*--------------------------------------------------------------*/
102
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200103#if defined(CONFIG_SYS_LOWBOOT)
104# if defined(CONFIG_SYS_RAMBOOT)
105# error CONFIG_SYS_LOWBOOT is incompatible with CONFIG_SYS_RAMBOOT
106# endif /* CONFIG_SYS_RAMBOOT */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200107 lis r4, CONFIG_SYS_DEFAULT_MBAR@h
108 lis r3, START_REG(CONFIG_SYS_BOOTCS_START)@h
109 ori r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
wdenk0a12b752004-03-11 22:46:36 +0000110 stw r3, 0x4(r4) /* CS0 start */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200111 lis r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
112 ori r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
wdenk0a12b752004-03-11 22:46:36 +0000113 stw r3, 0x8(r4) /* CS0 stop */
wdenk4b16c2e2003-11-07 13:42:26 +0000114 lis r3, 0x02010000@h
115 ori r3, r3, 0x02010000@l
wdenke44b9112004-04-18 23:32:11 +0000116 stw r3, 0x54(r4) /* CS0 and Boot enable */
wdenk4b16c2e2003-11-07 13:42:26 +0000117
wdenke44b9112004-04-18 23:32:11 +0000118 lis r3, lowboot_reentry@h /* jump from bootlow address space (0x0000xxxx) */
119 ori r3, r3, lowboot_reentry@l /* to the address space the linker used */
wdenk4b16c2e2003-11-07 13:42:26 +0000120 mtlr r3
wdenke44b9112004-04-18 23:32:11 +0000121 blr
wdenk1ebf41e2004-01-02 14:00:00 +0000122
123lowboot_reentry:
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200124 lis r3, START_REG(CONFIG_SYS_BOOTCS_START)@h
125 ori r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
wdenk0a12b752004-03-11 22:46:36 +0000126 stw r3, 0x4c(r4) /* Boot start */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200127 lis r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
128 ori r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
wdenk0a12b752004-03-11 22:46:36 +0000129 stw r3, 0x50(r4) /* Boot stop */
wdenk4b16c2e2003-11-07 13:42:26 +0000130 lis r3, 0x02000001@h
131 ori r3, r3, 0x02000001@l
wdenke44b9112004-04-18 23:32:11 +0000132 stw r3, 0x54(r4) /* Boot enable, CS0 disable */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200133#endif /* CONFIG_SYS_LOWBOOT */
wdenk1ebf41e2004-01-02 14:00:00 +0000134
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200135#if defined(CONFIG_SYS_DEFAULT_MBAR) && !defined(CONFIG_SYS_RAMBOOT)
136 lis r3, CONFIG_SYS_MBAR@h
137 ori r3, r3, CONFIG_SYS_MBAR@l
wdenk56ed43e2004-02-22 23:46:08 +0000138 /* MBAR is mirrored into the MBAR SPR */
139 mtspr MBAR,r3
wdenk21136db2003-07-16 21:53:01 +0000140 rlwinm r3, r3, 16, 16, 31
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200141 lis r4, CONFIG_SYS_DEFAULT_MBAR@h
wdenk21136db2003-07-16 21:53:01 +0000142 stw r3, 0(r4)
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200143#endif /* CONFIG_SYS_DEFAULT_MBAR */
wdenk21136db2003-07-16 21:53:01 +0000144
145 /* Initialise the MPC5xxx processor core */
146 /*--------------------------------------------------------------*/
147
148 bl init_5xxx_core
149
150 /* initialize some things that are hard to access from C */
151 /*--------------------------------------------------------------*/
152
153 /* set up stack in on-chip SRAM */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200154 lis r3, CONFIG_SYS_INIT_RAM_ADDR@h
155 ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
156 ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET
wdenk21136db2003-07-16 21:53:01 +0000157 li r0, 0 /* Make room for stack frame header and */
158 stwu r0, -4(r1) /* clear final stack frame so that */
159 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
160
161 /* let the C-code set up the rest */
162 /* */
163 /* Be careful to keep code relocatable ! */
164 /*--------------------------------------------------------------*/
165
Stefan Roese50b5ac02012-08-16 17:53:18 +0200166#ifndef CONFIG_SPL_BUILD
wdenk21136db2003-07-16 21:53:01 +0000167 GET_GOT /* initialize GOT access */
Stefan Roese50b5ac02012-08-16 17:53:18 +0200168#endif
Wolfgang Denkb2d36ea2011-04-20 22:11:21 +0200169
wdenk21136db2003-07-16 21:53:01 +0000170 /* r3: IMMR */
171 bl cpu_init_f /* run low-level CPU init code (in Flash)*/
172
Heiko Schocherba97b982015-11-25 09:46:19 +0100173 li r3, 0 /* parameter 1: bootflag */
wdenk21136db2003-07-16 21:53:01 +0000174 bl board_init_f /* run 1st part of board init code (in Flash)*/
175
Peter Tyser0c44caf2010-09-14 19:13:53 -0500176 /* NOTREACHED - board_init_f() does not return */
Stefan Roese50b5ac02012-08-16 17:53:18 +0200177#endif
Peter Tyser0c44caf2010-09-14 19:13:53 -0500178
Stefan Roese50b5ac02012-08-16 17:53:18 +0200179#ifndef CONFIG_SPL_BUILD
wdenk21136db2003-07-16 21:53:01 +0000180/*
181 * Vector Table
182 */
183
184 .globl _start_of_vectors
185_start_of_vectors:
186
187/* Machine check */
188 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
189
190/* Data Storage exception. */
191 STD_EXCEPTION(0x300, DataStorage, UnknownException)
192
193/* Instruction Storage exception. */
194 STD_EXCEPTION(0x400, InstStorage, UnknownException)
195
196/* External Interrupt exception. */
197 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
198
199/* Alignment exception. */
200 . = 0x600
201Alignment:
Rafal Jaworowski06244e42007-06-22 14:58:04 +0200202 EXCEPTION_PROLOG(SRR0, SRR1)
wdenk21136db2003-07-16 21:53:01 +0000203 mfspr r4,DAR
204 stw r4,_DAR(r21)
205 mfspr r5,DSISR
206 stw r5,_DSISR(r21)
207 addi r3,r1,STACK_FRAME_OVERHEAD
Joakim Tjernlund4ff6bc02010-01-19 14:41:55 +0100208 EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
wdenk21136db2003-07-16 21:53:01 +0000209
210/* Program check exception */
211 . = 0x700
212ProgramCheck:
Rafal Jaworowski06244e42007-06-22 14:58:04 +0200213 EXCEPTION_PROLOG(SRR0, SRR1)
wdenk21136db2003-07-16 21:53:01 +0000214 addi r3,r1,STACK_FRAME_OVERHEAD
Joakim Tjernlund4ff6bc02010-01-19 14:41:55 +0100215 EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
216 MSR_KERNEL, COPY_EE)
wdenk21136db2003-07-16 21:53:01 +0000217
218 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
219
220 /* I guess we could implement decrementer, and may have
221 * to someday for timekeeping.
222 */
223 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
224
225 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
226 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
wdenk874ac262003-07-24 23:38:38 +0000227 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
wdenk21136db2003-07-16 21:53:01 +0000228 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
229
230 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
231 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
232
233 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
234 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
235 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
236#ifdef DEBUG
237 . = 0x1300
238 /*
239 * This exception occurs when the program counter matches the
240 * Instruction Address Breakpoint Register (IABR).
241 *
242 * I want the cpu to halt if this occurs so I can hunt around
243 * with the debugger and look at things.
244 *
245 * When DEBUG is defined, both machine check enable (in the MSR)
246 * and checkstop reset enable (in the reset mode register) are
247 * turned off and so a checkstop condition will result in the cpu
248 * halting.
249 *
250 * I force the cpu into a checkstop condition by putting an illegal
251 * instruction here (at least this is the theory).
252 *
253 * well - that didnt work, so just do an infinite loop!
254 */
2551: b 1b
256#else
257 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
258#endif
259 STD_EXCEPTION(0x1400, SMI, UnknownException)
260
261 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
262 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
263 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
264 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
265 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
266 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
267 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
268 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
269 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
270 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
271 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
272 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
273 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
274 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
275 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
276 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
277 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
278 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
279 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
280 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
281 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
282 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
283 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
284 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
285 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
286 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
287 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
288
289
290 .globl _end_of_vectors
291_end_of_vectors:
292
293 . = 0x3000
294
295/*
296 * This code finishes saving the registers to the exception frame
297 * and jumps to the appropriate handler for the exception.
298 * Register r21 is pointer into trap frame, r1 has new stack pointer.
299 */
300 .globl transfer_to_handler
301transfer_to_handler:
302 stw r22,_NIP(r21)
303 lis r22,MSR_POW@h
304 andc r23,r23,r22
305 stw r23,_MSR(r21)
306 SAVE_GPR(7, r21)
307 SAVE_4GPRS(8, r21)
308 SAVE_8GPRS(12, r21)
309 SAVE_8GPRS(24, r21)
310 mflr r23
311 andi. r24,r23,0x3f00 /* get vector offset */
312 stw r24,TRAP(r21)
313 li r22,0
314 stw r22,RESULT(r21)
315 lwz r24,0(r23) /* virtual address of handler */
316 lwz r23,4(r23) /* where to go when done */
317 mtspr SRR0,r24
318 mtspr SRR1,r20
319 mtlr r23
320 SYNC
321 rfi /* jump to handler, enable MMU */
322
323int_return:
324 mfmsr r28 /* Disable interrupts */
325 li r4,0
326 ori r4,r4,MSR_EE
327 andc r28,r28,r4
328 SYNC /* Some chip revs need this... */
329 mtmsr r28
330 SYNC
331 lwz r2,_CTR(r1)
332 lwz r0,_LINK(r1)
333 mtctr r2
334 mtlr r0
335 lwz r2,_XER(r1)
336 lwz r0,_CCR(r1)
337 mtspr XER,r2
338 mtcrf 0xFF,r0
339 REST_10GPRS(3, r1)
340 REST_10GPRS(13, r1)
341 REST_8GPRS(23, r1)
342 REST_GPR(31, r1)
343 lwz r2,_NIP(r1) /* Restore environment */
344 lwz r0,_MSR(r1)
345 mtspr SRR0,r2
346 mtspr SRR1,r0
347 lwz r0,GPR0(r1)
348 lwz r2,GPR2(r1)
349 lwz r1,GPR1(r1)
350 SYNC
351 rfi
Stefan Roese50b5ac02012-08-16 17:53:18 +0200352#endif /* CONFIG_SPL_BUILD */
wdenk21136db2003-07-16 21:53:01 +0000353
354/*
355 * This code initialises the MPC5xxx processor core
356 * (conforms to PowerPC 603e spec)
357 * Note: expects original MSR contents to be in r5.
358 */
359
360 .globl init_5xx_core
361init_5xxx_core:
362
363 /* Initialize machine status; enable machine check interrupt */
364 /*--------------------------------------------------------------*/
365
366 li r3, MSR_KERNEL /* Set ME and RI flags */
367 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
368#ifdef DEBUG
369 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
370#endif
371 SYNC /* Some chip revs need this... */
372 mtmsr r3
373 SYNC
374 mtspr SRR1, r3 /* Make SRR1 match MSR */
375
376 /* Initialize the Hardware Implementation-dependent Registers */
377 /* HID0 also contains cache control */
378 /*--------------------------------------------------------------*/
379
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200380 lis r3, CONFIG_SYS_HID0_INIT@h
381 ori r3, r3, CONFIG_SYS_HID0_INIT@l
wdenk21136db2003-07-16 21:53:01 +0000382 SYNC
383 mtspr HID0, r3
384
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200385 lis r3, CONFIG_SYS_HID0_FINAL@h
386 ori r3, r3, CONFIG_SYS_HID0_FINAL@l
wdenk21136db2003-07-16 21:53:01 +0000387 SYNC
388 mtspr HID0, r3
389
390 /* clear all BAT's */
391 /*--------------------------------------------------------------*/
392
393 li r0, 0
394 mtspr DBAT0U, r0
395 mtspr DBAT0L, r0
396 mtspr DBAT1U, r0
397 mtspr DBAT1L, r0
398 mtspr DBAT2U, r0
399 mtspr DBAT2L, r0
400 mtspr DBAT3U, r0
401 mtspr DBAT3L, r0
wdenkfc314ce2003-09-14 19:08:39 +0000402 mtspr DBAT4U, r0
403 mtspr DBAT4L, r0
404 mtspr DBAT5U, r0
405 mtspr DBAT5L, r0
406 mtspr DBAT6U, r0
407 mtspr DBAT6L, r0
408 mtspr DBAT7U, r0
409 mtspr DBAT7L, r0
wdenk21136db2003-07-16 21:53:01 +0000410 mtspr IBAT0U, r0
411 mtspr IBAT0L, r0
412 mtspr IBAT1U, r0
413 mtspr IBAT1L, r0
414 mtspr IBAT2U, r0
415 mtspr IBAT2L, r0
416 mtspr IBAT3U, r0
417 mtspr IBAT3L, r0
wdenkfc314ce2003-09-14 19:08:39 +0000418 mtspr IBAT4U, r0
419 mtspr IBAT4L, r0
420 mtspr IBAT5U, r0
421 mtspr IBAT5L, r0
422 mtspr IBAT6U, r0
423 mtspr IBAT6L, r0
424 mtspr IBAT7U, r0
425 mtspr IBAT7L, r0
wdenk21136db2003-07-16 21:53:01 +0000426 SYNC
427
428 /* invalidate all tlb's */
429 /* */
430 /* From the 603e User Manual: "The 603e provides the ability to */
431 /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
432 /* instruction invalidates the TLB entry indexed by the EA, and */
433 /* operates on both the instruction and data TLBs simultaneously*/
434 /* invalidating four TLB entries (both sets in each TLB). The */
435 /* index corresponds to bits 15-19 of the EA. To invalidate all */
436 /* entries within both TLBs, 32 tlbie instructions should be */
437 /* issued, incrementing this field by one each time." */
438 /* */
439 /* "Note that the tlbia instruction is not implemented on the */
440 /* 603e." */
441 /* */
442 /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
443 /* incrementing by 0x1000 each time. The code below is sort of */
Stefan Roese88fbf932010-04-15 16:07:28 +0200444 /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S */
wdenk21136db2003-07-16 21:53:01 +0000445 /* */
446 /*--------------------------------------------------------------*/
447
448 li r3, 32
449 mtctr r3
450 li r3, 0
4511: tlbie r3
452 addi r3, r3, 0x1000
453 bdnz 1b
454 SYNC
455
456 /* Done! */
457 /*--------------------------------------------------------------*/
458
459 blr
460
461/* Cache functions.
462 *
463 * Note: requires that all cache bits in
464 * HID0 are in the low half word.
465 */
466 .globl icache_enable
467icache_enable:
468 mfspr r3, HID0
469 ori r3, r3, HID0_ICE
470 lis r4, 0
471 ori r4, r4, HID0_ILOCK
472 andc r3, r3, r4
473 ori r4, r3, HID0_ICFI
474 isync
475 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
476 isync
477 mtspr HID0, r3 /* clears invalidate */
478 blr
479
480 .globl icache_disable
481icache_disable:
482 mfspr r3, HID0
483 lis r4, 0
484 ori r4, r4, HID0_ICE|HID0_ILOCK
485 andc r3, r3, r4
486 ori r4, r3, HID0_ICFI
487 isync
488 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
489 isync
490 mtspr HID0, r3 /* clears invalidate */
491 blr
492
493 .globl icache_status
494icache_status:
495 mfspr r3, HID0
496 rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
497 blr
498
499 .globl dcache_enable
500dcache_enable:
501 mfspr r3, HID0
502 ori r3, r3, HID0_DCE
503 lis r4, 0
504 ori r4, r4, HID0_DLOCK
505 andc r3, r3, r4
506 ori r4, r3, HID0_DCI
507 sync
508 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
509 sync
510 mtspr HID0, r3 /* clears invalidate */
511 blr
512
513 .globl dcache_disable
514dcache_disable:
515 mfspr r3, HID0
516 lis r4, 0
517 ori r4, r4, HID0_DCE|HID0_DLOCK
518 andc r3, r3, r4
519 ori r4, r3, HID0_DCI
520 sync
521 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
522 sync
523 mtspr HID0, r3 /* clears invalidate */
524 blr
525
526 .globl dcache_status
527dcache_status:
528 mfspr r3, HID0
529 rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
530 blr
531
wdenk2d644822004-06-09 17:45:32 +0000532 .globl get_svr
533get_svr:
534 mfspr r3, SVR
535 blr
536
wdenk21136db2003-07-16 21:53:01 +0000537 .globl get_pvr
538get_pvr:
539 mfspr r3, PVR
540 blr
541
Stefan Roese50b5ac02012-08-16 17:53:18 +0200542#ifndef CONFIG_SPL_BUILD
wdenk21136db2003-07-16 21:53:01 +0000543/*------------------------------------------------------------------------------*/
544
545/*
546 * void relocate_code (addr_sp, gd, addr_moni)
547 *
548 * This "function" does not return, instead it continues in RAM
549 * after relocating the monitor code.
550 *
551 * r3 = dest
552 * r4 = src
553 * r5 = length in bytes
554 * r6 = cachelinesize
555 */
556 .globl relocate_code
557relocate_code:
558 mr r1, r3 /* Set new stack pointer */
559 mr r9, r4 /* Save copy of Global Data pointer */
560 mr r10, r5 /* Save copy of Destination Address */
561
Joakim Tjernlund3fbaa4d2010-01-19 14:41:56 +0100562 GET_GOT
wdenk21136db2003-07-16 21:53:01 +0000563 mr r3, r5 /* Destination Address */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200564 lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
565 ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
wdenk21136db2003-07-16 21:53:01 +0000566 lwz r5, GOT(__init_end)
567 sub r5, r5, r4
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200568 li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
wdenk21136db2003-07-16 21:53:01 +0000569
570 /*
571 * Fix GOT pointer:
572 *
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200573 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
wdenk21136db2003-07-16 21:53:01 +0000574 *
575 * Offset:
576 */
577 sub r15, r10, r4
578
579 /* First our own GOT */
Joakim Tjernlund3fbaa4d2010-01-19 14:41:56 +0100580 add r12, r12, r15
wdenk21136db2003-07-16 21:53:01 +0000581 /* then the one used by the C code */
582 add r30, r30, r15
583
584 /*
585 * Now relocate code
586 */
587
588 cmplw cr1,r3,r4
589 addi r0,r5,3
590 srwi. r0,r0,2
591 beq cr1,4f /* In place copy is not necessary */
592 beq 7f /* Protect against 0 count */
593 mtctr r0
594 bge cr1,2f
595
596 la r8,-4(r4)
597 la r7,-4(r3)
5981: lwzu r0,4(r8)
599 stwu r0,4(r7)
600 bdnz 1b
601 b 4f
602
6032: slwi r0,r0,2
604 add r8,r4,r0
605 add r7,r3,r0
6063: lwzu r0,-4(r8)
607 stwu r0,-4(r7)
608 bdnz 3b
609
610/*
611 * Now flush the cache: note that we must start from a cache aligned
612 * address. Otherwise we might miss one cache line.
613 */
6144: cmpwi r6,0
615 add r5,r3,r5
616 beq 7f /* Always flush prefetch queue in any case */
617 subi r0,r6,1
618 andc r3,r3,r0
619 mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
620 rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
621 cmpwi r7,0
622 beq 9f
623 mr r4,r3
6245: dcbst 0,r4
625 add r4,r4,r6
626 cmplw r4,r5
627 blt 5b
628 sync /* Wait for all dcbst to complete on bus */
6299: mfspr r7,HID0 /* don't do icbi if icache is disabled */
630 rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
631 cmpwi r7,0
632 beq 7f
633 mr r4,r3
6346: icbi 0,r4
635 add r4,r4,r6
636 cmplw r4,r5
637 blt 6b
6387: sync /* Wait for all icbi to complete on bus */
639 isync
640
641/*
642 * We are done. Do not return, instead branch to second part of board
643 * initialization, now running from RAM.
644 */
645
646 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
647 mtlr r0
648 blr
649
650in_ram:
651
652 /*
Joakim Tjernlund3fbaa4d2010-01-19 14:41:56 +0100653 * Relocation Function, r12 point to got2+0x8000
wdenk21136db2003-07-16 21:53:01 +0000654 *
655 * Adjust got2 pointers, no need to check for 0, this code
656 * already puts a few entries in the table.
657 */
658 li r0,__got2_entries@sectoff@l
659 la r3,GOT(_GOT2_TABLE_)
660 lwz r11,GOT(_GOT2_TABLE_)
661 mtctr r0
662 sub r11,r3,r11
663 addi r3,r3,-4
6641: lwzu r0,4(r3)
Joakim Tjernlund4f2fdac2009-10-08 02:03:51 +0200665 cmpwi r0,0
666 beq- 2f
wdenk21136db2003-07-16 21:53:01 +0000667 add r0,r0,r11
668 stw r0,0(r3)
Joakim Tjernlund4f2fdac2009-10-08 02:03:51 +02006692: bdnz 1b
wdenk21136db2003-07-16 21:53:01 +0000670
671 /*
672 * Now adjust the fixups and the pointers to the fixups
673 * in case we need to move ourselves again.
674 */
Joakim Tjernlund4f2fdac2009-10-08 02:03:51 +0200675 li r0,__fixup_entries@sectoff@l
wdenk21136db2003-07-16 21:53:01 +0000676 lwz r3,GOT(_FIXUP_TABLE_)
677 cmpwi r0,0
678 mtctr r0
679 addi r3,r3,-4
680 beq 4f
6813: lwzu r4,4(r3)
682 lwzux r0,r4,r11
Joakim Tjernlundc61b25a2010-10-14 11:51:44 +0200683 cmpwi r0,0
wdenk21136db2003-07-16 21:53:01 +0000684 add r0,r0,r11
Joakim Tjernlund401b5922010-11-04 19:02:00 +0100685 stw r4,0(r3)
Joakim Tjernlundc61b25a2010-10-14 11:51:44 +0200686 beq- 5f
wdenk21136db2003-07-16 21:53:01 +0000687 stw r0,0(r4)
Joakim Tjernlundc61b25a2010-10-14 11:51:44 +02006885: bdnz 3b
wdenk21136db2003-07-16 21:53:01 +00006894:
690clear_bss:
691 /*
692 * Now clear BSS segment
693 */
694 lwz r3,GOT(__bss_start)
Simon Glassed70c8f2013-03-14 06:54:53 +0000695 lwz r4,GOT(__bss_end)
wdenk21136db2003-07-16 21:53:01 +0000696
697 cmplw 0, r3, r4
698 beq 6f
699
700 li r0, 0
7015:
702 stw r0, 0(r3)
703 addi r3, r3, 4
704 cmplw 0, r3, r4
705 bne 5b
7066:
707
708 mr r3, r9 /* Global Data pointer */
709 mr r4, r10 /* Destination Address */
710 bl board_init_r
711
712 /*
713 * Copy exception vector code to low memory
714 *
715 * r3: dest_addr
716 * r7: source address, r8: end address, r9: target address
717 */
718 .globl trap_init
719trap_init:
Joakim Tjernlund3fbaa4d2010-01-19 14:41:56 +0100720 mflr r4 /* save link register */
721 GET_GOT
wdenk21136db2003-07-16 21:53:01 +0000722 lwz r7, GOT(_start)
723 lwz r8, GOT(_end_of_vectors)
724
725 li r9, 0x100 /* reset vector always at 0x100 */
726
727 cmplw 0, r7, r8
728 bgelr /* return if r7>=r8 - just in case */
wdenk21136db2003-07-16 21:53:01 +00007291:
730 lwz r0, 0(r7)
731 stw r0, 0(r9)
732 addi r7, r7, 4
733 addi r9, r9, 4
734 cmplw 0, r7, r8
735 bne 1b
736
737 /*
738 * relocate `hdlr' and `int_return' entries
739 */
740 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
741 li r8, Alignment - _start + EXC_OFF_SYS_RESET
7422:
743 bl trap_reloc
744 addi r7, r7, 0x100 /* next exception vector */
745 cmplw 0, r7, r8
746 blt 2b
747
748 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
749 bl trap_reloc
750
751 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
752 bl trap_reloc
753
754 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
755 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
7563:
757 bl trap_reloc
758 addi r7, r7, 0x100 /* next exception vector */
759 cmplw 0, r7, r8
760 blt 3b
761
762 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
763 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
7644:
765 bl trap_reloc
766 addi r7, r7, 0x100 /* next exception vector */
767 cmplw 0, r7, r8
768 blt 4b
769
770 mfmsr r3 /* now that the vectors have */
771 lis r7, MSR_IP@h /* relocated into low memory */
772 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
773 andc r3, r3, r7 /* (if it was on) */
774 SYNC /* Some chip revs need this... */
775 mtmsr r3
776 SYNC
777
778 mtlr r4 /* restore link register */
779 blr
Stefan Roese50b5ac02012-08-16 17:53:18 +0200780
781#endif /* CONFIG_SPL_BUILD */