]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/powerpc/cpu/mpc8260/start.S
powerpc: remove cogent_8xx, cogent_mpc8260 board support
[people/ms/u-boot.git] / arch / powerpc / cpu / mpc8260 / start.S
1 /*
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, 2001,2002 Wolfgang Denk <wd@denx.de>
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 */
8
9 /*
10 * U-Boot - Startup Code for MPC8260 PowerPC based Embedded Boards
11 */
12 #include <asm-offsets.h>
13 #include <config.h>
14 #include <mpc8260.h>
15 #include <version.h>
16
17 #include <ppc_asm.tmpl>
18 #include <ppc_defs.h>
19
20 #include <asm/cache.h>
21 #include <asm/mmu.h>
22 #include <asm/u-boot.h>
23
24 /* 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
34 /*
35 * Set up GOT: Global Offset Table
36 *
37 * Use r12 to access the GOT
38 */
39 START_GOT
40 GOT_ENTRY(_GOT2_TABLE_)
41 GOT_ENTRY(_FIXUP_TABLE_)
42
43 GOT_ENTRY(_start)
44 GOT_ENTRY(_start_of_vectors)
45 GOT_ENTRY(_end_of_vectors)
46 GOT_ENTRY(transfer_to_handler)
47
48 GOT_ENTRY(__init_end)
49 GOT_ENTRY(__bss_end)
50 GOT_ENTRY(__bss_start)
51 END_GOT
52
53 /*
54 * Version string - must be in data segment because MPC8260 uses the first
55 * 256 bytes for the Hard Reset Configuration Word table (see below).
56 * Similarly, can't have the U-Boot Magic Number as the first thing in
57 * the image - don't know how this will affect the image tools, but I guess
58 * I'll find out soon
59 */
60 .data
61 .globl version_string
62 version_string:
63 .ascii U_BOOT_VERSION_STRING, "\0"
64
65 /*
66 * Hard Reset Configuration Word (HRCW) table
67 *
68 * The Hard Reset Configuration Word (HRCW) sets a number of useful things
69 * such as whether there is an external memory controller, whether the
70 * PowerPC core is disabled (i.e. only the communications processor is
71 * active, accessed by another CPU on the bus), whether using external
72 * arbitration, external bus mode, boot port size, core initial prefix,
73 * internal space base, boot memory space, etc.
74 *
75 * These things dictate where the processor begins execution, where the
76 * boot ROM appears in memory, the memory controller setup when access
77 * boot ROM, etc. The HRCW is *extremely* important.
78 *
79 * The HRCW is read from the bus during reset. One CPU on the bus will
80 * be a hard reset configuration master, any others will be hard reset
81 * configuration slaves. The master reads eight HRCWs from flash during
82 * reset - the first it uses for itself, the other 7 it communicates to
83 * up to 7 configuration slaves by some complicated mechanism, which is
84 * not really important here.
85 *
86 * The configuration master performs 32 successive reads starting at address
87 * 0 and incrementing by 8 each read (i.e. on 64 bit boundaries) but only 8
88 * bits is read, and always from byte lane D[0-7] (so that port size of the
89 * boot device does not matter). The first four reads form the 32 bit HRCW
90 * for the master itself. The second four reads form the HRCW for the first
91 * slave, and so on, up to seven slaves. The 32 bit HRCW is formed by
92 * concatenating the four bytes, with the first read placed in byte 0 (the
93 * most significant byte), and so on with the fourth read placed in byte 3
94 * (the least significant byte).
95 */
96 #define _HRCW_TABLE_ENTRY(w) \
97 .fill 8,1,(((w)>>24)&0xff); \
98 .fill 8,1,(((w)>>16)&0xff); \
99 .fill 8,1,(((w)>> 8)&0xff); \
100 .fill 8,1,(((w) )&0xff)
101 .text
102 .globl _hrcw_table
103 _hrcw_table:
104 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_MASTER)
105 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE1)
106 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE2)
107 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE3)
108 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE4)
109 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE5)
110 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE6)
111 _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE7)
112 /*
113 * After configuration, a system reset exception is executed using the
114 * vector at offset 0x100 relative to the base set by MSR[IP]. If MSR[IP]
115 * is 0, the base address is 0x00000000. If MSR[IP] is 1, the base address
116 * is 0xfff00000. In the case of a Power On Reset or Hard Reset, the value
117 * of MSR[IP] is determined by the CIP field in the HRCW.
118 *
119 * Other bits in the HRCW set up the Base Address and Port Size in BR0.
120 * This determines the location of the boot ROM (flash or EPROM) in the
121 * processor's address space at boot time. As long as the HRCW is set up
122 * so that we eventually end up executing the code below when the processor
123 * executes the reset exception, the actual values used should not matter.
124 *
125 * Once we have got here, the address mask in OR0 is cleared so that the
126 * bottom 32K of the boot ROM is effectively repeated all throughout the
127 * processor's address space, after which we can jump to the absolute
128 * address at which the boot ROM was linked at compile time, and proceed
129 * to initialise the memory controller without worrying if the rug will be
130 * pulled out from under us, so to speak (it will be fine as long as we
131 * configure BR0 with the same boot ROM link address).
132 */
133 . = EXC_OFF_SYS_RESET
134
135 .globl _start
136 _start:
137 mfmsr r5 /* save msr contents */
138
139 #if defined(CONFIG_SYS_DEFAULT_IMMR)
140 lis r3, CONFIG_SYS_IMMR@h
141 ori r3, r3, CONFIG_SYS_IMMR@l
142 lis r4, CONFIG_SYS_DEFAULT_IMMR@h
143 stw r3, 0x1A8(r4)
144 #endif /* CONFIG_SYS_DEFAULT_IMMR */
145
146 /* Initialise the MPC8260 processor core */
147 /*--------------------------------------------------------------*/
148
149 bl init_8260_core
150
151 #ifndef CONFIG_SYS_RAMBOOT
152 /* When booting from ROM (Flash or EPROM), clear the */
153 /* Address Mask in OR0 so ROM appears everywhere */
154 /*--------------------------------------------------------------*/
155
156 lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
157 lwz r4, IM_OR0@l(r3)
158 li r5, 0x7fff
159 and r4, r4, r5
160 stw r4, IM_OR0@l(r3)
161
162 /* Calculate absolute address in FLASH and jump there */
163 /*--------------------------------------------------------------*/
164
165 lis r3, CONFIG_SYS_MONITOR_BASE@h
166 ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
167 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
168 mtlr r3
169 blr
170
171 in_flash:
172 #endif /* CONFIG_SYS_RAMBOOT */
173
174 /* initialize some things that are hard to access from C */
175 /*--------------------------------------------------------------*/
176
177 lis r3, CONFIG_SYS_IMMR@h /* set up stack in internal DPRAM */
178 ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET
179 li r0, 0 /* Make room for stack frame header and */
180 stwu r0, -4(r1) /* clear final stack frame so that */
181 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
182
183 /* let the C-code set up the rest */
184 /* */
185 /* Be careful to keep code relocatable ! */
186 /*--------------------------------------------------------------*/
187
188 GET_GOT /* initialize GOT access */
189
190 /* r3: IMMR */
191 bl cpu_init_f /* run low-level CPU init code (in Flash)*/
192
193 #ifdef DEBUG
194 bl init_debug /* set up debugging stuff */
195 #endif
196
197 bl board_init_f /* run 1st part of board init code (in Flash)*/
198
199 /* NOTREACHED - board_init_f() does not return */
200
201 /*
202 * Vector Table
203 */
204
205 .globl _start_of_vectors
206 _start_of_vectors:
207
208 /* Machine check */
209 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
210
211 /* Data Storage exception. */
212 STD_EXCEPTION(0x300, DataStorage, UnknownException)
213
214 /* Instruction Storage exception. */
215 STD_EXCEPTION(0x400, InstStorage, UnknownException)
216
217 /* External Interrupt exception. */
218 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
219
220 /* Alignment exception. */
221 . = 0x600
222 Alignment:
223 EXCEPTION_PROLOG(SRR0, SRR1)
224 mfspr r4,DAR
225 stw r4,_DAR(r21)
226 mfspr r5,DSISR
227 stw r5,_DSISR(r21)
228 addi r3,r1,STACK_FRAME_OVERHEAD
229 EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
230
231 /* Program check exception */
232 . = 0x700
233 ProgramCheck:
234 EXCEPTION_PROLOG(SRR0, SRR1)
235 addi r3,r1,STACK_FRAME_OVERHEAD
236 EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
237 MSR_KERNEL, COPY_EE)
238
239 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
240
241 /* I guess we could implement decrementer, and may have
242 * to someday for timekeeping.
243 */
244 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
245
246 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
247 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
248 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
249 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
250
251 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
252 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
253
254 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
255 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
256 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
257 #ifdef DEBUG
258 . = 0x1300
259 /*
260 * This exception occurs when the program counter matches the
261 * Instruction Address Breakpoint Register (IABR).
262 *
263 * I want the cpu to halt if this occurs so I can hunt around
264 * with the debugger and look at things.
265 *
266 * When DEBUG is defined, both machine check enable (in the MSR)
267 * and checkstop reset enable (in the reset mode register) are
268 * turned off and so a checkstop condition will result in the cpu
269 * halting.
270 *
271 * I force the cpu into a checkstop condition by putting an illegal
272 * instruction here (at least this is the theory).
273 *
274 * well - that didnt work, so just do an infinite loop!
275 */
276 1: b 1b
277 #else
278 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
279 #endif
280 STD_EXCEPTION(0x1400, SMI, UnknownException)
281
282 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
283 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
284 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
285 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
286 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
287 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
288 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
289 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
290 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
291 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
292 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
293 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
294 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
295 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
296 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
297 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
298 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
299 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
300 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
301 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
302 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
303 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
304 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
305 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
306 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
307 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
308 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
309
310
311 .globl _end_of_vectors
312 _end_of_vectors:
313
314 . = 0x3000
315
316 /*
317 * This code finishes saving the registers to the exception frame
318 * and jumps to the appropriate handler for the exception.
319 * Register r21 is pointer into trap frame, r1 has new stack pointer.
320 */
321 .globl transfer_to_handler
322 transfer_to_handler:
323 stw r22,_NIP(r21)
324 lis r22,MSR_POW@h
325 andc r23,r23,r22
326 stw r23,_MSR(r21)
327 SAVE_GPR(7, r21)
328 SAVE_4GPRS(8, r21)
329 SAVE_8GPRS(12, r21)
330 SAVE_8GPRS(24, r21)
331 mflr r23
332 andi. r24,r23,0x3f00 /* get vector offset */
333 stw r24,TRAP(r21)
334 li r22,0
335 stw r22,RESULT(r21)
336 lwz r24,0(r23) /* virtual address of handler */
337 lwz r23,4(r23) /* where to go when done */
338 mtspr SRR0,r24
339 mtspr SRR1,r20
340 mtlr r23
341 SYNC
342 rfi /* jump to handler, enable MMU */
343
344 int_return:
345 mfmsr r28 /* Disable interrupts */
346 li r4,0
347 ori r4,r4,MSR_EE
348 andc r28,r28,r4
349 SYNC /* Some chip revs need this... */
350 mtmsr r28
351 SYNC
352 lwz r2,_CTR(r1)
353 lwz r0,_LINK(r1)
354 mtctr r2
355 mtlr r0
356 lwz r2,_XER(r1)
357 lwz r0,_CCR(r1)
358 mtspr XER,r2
359 mtcrf 0xFF,r0
360 REST_10GPRS(3, r1)
361 REST_10GPRS(13, r1)
362 REST_8GPRS(23, r1)
363 REST_GPR(31, r1)
364 lwz r2,_NIP(r1) /* Restore environment */
365 lwz r0,_MSR(r1)
366 mtspr SRR0,r2
367 mtspr SRR1,r0
368 lwz r0,GPR0(r1)
369 lwz r2,GPR2(r1)
370 lwz r1,GPR1(r1)
371 SYNC
372 rfi
373
374 /*
375 * This code initialises the MPC8260 processor core
376 * (conforms to PowerPC 603e spec)
377 * Note: expects original MSR contents to be in r5.
378 */
379
380 .globl init_8260_core
381 init_8260_core:
382
383 /* Initialize machine status; enable machine check interrupt */
384 /*--------------------------------------------------------------*/
385
386 li r3, MSR_KERNEL /* Set ME and RI flags */
387 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
388 #ifdef DEBUG
389 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
390 #endif
391 SYNC /* Some chip revs need this... */
392 mtmsr r3
393 SYNC
394 mtspr SRR1, r3 /* Make SRR1 match MSR */
395
396 /* Initialise the SYPCR early, and reset the watchdog (if req) */
397 /*--------------------------------------------------------------*/
398
399 lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
400 lis r4, CONFIG_SYS_SYPCR@h
401 ori r4, r4, CONFIG_SYS_SYPCR@l
402 stw r4, IM_SYPCR@l(r3)
403 #if defined(CONFIG_WATCHDOG)
404 li r4, 21868 /* = 0x556c */
405 sth r4, IM_SWSR@l(r3)
406 li r4, -21959 /* = 0xaa39 */
407 sth r4, IM_SWSR@l(r3)
408 #endif /* CONFIG_WATCHDOG */
409
410 /* Initialize the Hardware Implementation-dependent Registers */
411 /* HID0 also contains cache control */
412 /*--------------------------------------------------------------*/
413
414 lis r3, CONFIG_SYS_HID0_INIT@h
415 ori r3, r3, CONFIG_SYS_HID0_INIT@l
416 SYNC
417 mtspr HID0, r3
418
419 lis r3, CONFIG_SYS_HID0_FINAL@h
420 ori r3, r3, CONFIG_SYS_HID0_FINAL@l
421 SYNC
422 mtspr HID0, r3
423
424 lis r3, CONFIG_SYS_HID2@h
425 ori r3, r3, CONFIG_SYS_HID2@l
426 mtspr HID2, r3
427
428 /* clear all BAT's */
429 /*--------------------------------------------------------------*/
430
431 li r0, 0
432 mtspr DBAT0U, r0
433 mtspr DBAT0L, r0
434 mtspr DBAT1U, r0
435 mtspr DBAT1L, r0
436 mtspr DBAT2U, r0
437 mtspr DBAT2L, r0
438 mtspr DBAT3U, r0
439 mtspr DBAT3L, r0
440 mtspr IBAT0U, r0
441 mtspr IBAT0L, r0
442 mtspr IBAT1U, r0
443 mtspr IBAT1L, r0
444 mtspr IBAT2U, r0
445 mtspr IBAT2L, r0
446 mtspr IBAT3U, r0
447 mtspr IBAT3L, r0
448 SYNC
449
450 /* invalidate all tlb's */
451 /* */
452 /* From the 603e User Manual: "The 603e provides the ability to */
453 /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
454 /* instruction invalidates the TLB entry indexed by the EA, and */
455 /* operates on both the instruction and data TLBs simultaneously*/
456 /* invalidating four TLB entries (both sets in each TLB). The */
457 /* index corresponds to bits 15-19 of the EA. To invalidate all */
458 /* entries within both TLBs, 32 tlbie instructions should be */
459 /* issued, incrementing this field by one each time." */
460 /* */
461 /* "Note that the tlbia instruction is not implemented on the */
462 /* 603e." */
463 /* */
464 /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
465 /* incrementing by 0x1000 each time. The code below is sort of */
466 /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S */
467 /* */
468 /*--------------------------------------------------------------*/
469
470 li r3, 32
471 mtctr r3
472 li r3, 0
473 1: tlbie r3
474 addi r3, r3, 0x1000
475 bdnz 1b
476 SYNC
477
478 /* Done! */
479 /*--------------------------------------------------------------*/
480
481 blr
482
483 #ifdef DEBUG
484
485 /*
486 * initialise things related to debugging.
487 *
488 * must be called after the global offset table (GOT) is initialised
489 * (GET_GOT) and after cpu_init_f() has executed.
490 */
491
492 .globl init_debug
493 init_debug:
494
495 lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
496
497 /* Quick and dirty hack to enable the RAM and copy the */
498 /* vectors so that we can take exceptions. */
499 /*--------------------------------------------------------------*/
500 /* write Memory Refresh Prescaler */
501 li r4, CONFIG_SYS_MPTPR
502 sth r4, IM_MPTPR@l(r3)
503 /* write 60x Refresh Timer */
504 li r4, CONFIG_SYS_PSRT
505 stb r4, IM_PSRT@l(r3)
506 /* init the 60x SDRAM Mode Register */
507 lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@h
508 ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@l
509 stw r4, IM_PSDMR@l(r3)
510 /* write Precharge All Banks command */
511 lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@h
512 ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@l
513 stw r4, IM_PSDMR@l(r3)
514 stb r0, 0(0)
515 /* write eight CBR Refresh commands */
516 lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@h
517 ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@l
518 stw r4, IM_PSDMR@l(r3)
519 stb r0, 0(0)
520 stb r0, 0(0)
521 stb r0, 0(0)
522 stb r0, 0(0)
523 stb r0, 0(0)
524 stb r0, 0(0)
525 stb r0, 0(0)
526 stb r0, 0(0)
527 /* write Mode Register Write command */
528 lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@h
529 ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@l
530 stw r4, IM_PSDMR@l(r3)
531 stb r0, 0(0)
532 /* write Normal Operation command and enable Refresh */
533 lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
534 ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
535 stw r4, IM_PSDMR@l(r3)
536 stb r0, 0(0)
537 /* RAM should now be operational */
538
539 #define VEC_WRD_CNT ((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
540 mflr r3
541 GET_GOT
542 mtlr r3
543 lwz r3, GOT(_end_of_vectors)
544 rlwinm r4, r3, 0, 18, 31 /* _end_of_vectors & 0x3FFF */
545 lis r5, VEC_WRD_CNT@h
546 ori r5, r5, VEC_WRD_CNT@l
547 mtctr r5
548 1:
549 lwzu r5, -4(r3)
550 stwu r5, -4(r4)
551 bdnz 1b
552
553 /* Load the Instruction Address Breakpoint Register (IABR). */
554 /* */
555 /* The address to load is stored in the first word of dual port */
556 /* ram and should be preserved while the power is on, so you */
557 /* can plug addresses into that location then reset the cpu and */
558 /* this code will load that address into the IABR after the */
559 /* reset. */
560 /* */
561 /* When the program counter matches the contents of the IABR, */
562 /* an exception is generated (before the instruction at that */
563 /* location completes). The vector for this exception is 0x1300 */
564 /*--------------------------------------------------------------*/
565 lis r3, CONFIG_SYS_IMMR@h
566 lwz r3, 0(r3)
567 mtspr IABR, r3
568
569 /* Set the entire dual port RAM (where the initial stack */
570 /* resides) to a known value - makes it easier to see where */
571 /* the stack has been written */
572 /*--------------------------------------------------------------*/
573 lis r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@h
574 ori r3, r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@l
575 li r4, ((CONFIG_SYS_INIT_SP_OFFSET - 4) / 4)
576 mtctr r4
577 lis r4, 0xdeadbeaf@h
578 ori r4, r4, 0xdeadbeaf@l
579 1:
580 stwu r4, -4(r3)
581 bdnz 1b
582
583 /* Done! */
584 /*--------------------------------------------------------------*/
585
586 blr
587 #endif
588
589 /* Cache functions.
590 *
591 * Note: requires that all cache bits in
592 * HID0 are in the low half word.
593 */
594 .globl icache_enable
595 icache_enable:
596 mfspr r3, HID0
597 ori r3, r3, HID0_ICE
598 lis r4, 0
599 ori r4, r4, HID0_ILOCK
600 andc r3, r3, r4
601 ori r4, r3, HID0_ICFI
602 isync
603 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
604 isync
605 mtspr HID0, r3 /* clears invalidate */
606 blr
607
608 .globl icache_disable
609 icache_disable:
610 mfspr r3, HID0
611 lis r4, 0
612 ori r4, r4, HID0_ICE|HID0_ILOCK
613 andc r3, r3, r4
614 ori r4, r3, HID0_ICFI
615 isync
616 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
617 isync
618 mtspr HID0, r3 /* clears invalidate */
619 blr
620
621 .globl icache_status
622 icache_status:
623 mfspr r3, HID0
624 rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
625 blr
626
627 .globl dcache_enable
628 dcache_enable:
629 mfspr r3, HID0
630 ori r3, r3, HID0_DCE
631 lis r4, 0
632 ori r4, r4, HID0_DLOCK
633 andc r3, r3, r4
634 ori r4, r3, HID0_DCI
635 sync
636 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
637 sync
638 mtspr HID0, r3 /* clears invalidate */
639 blr
640
641 .globl dcache_disable
642 dcache_disable:
643 mfspr r3, HID0
644 lis r4, 0
645 ori r4, r4, HID0_DCE|HID0_DLOCK
646 andc r3, r3, r4
647 ori r4, r3, HID0_DCI
648 sync
649 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
650 sync
651 mtspr HID0, r3 /* clears invalidate */
652 blr
653
654 .globl dcache_status
655 dcache_status:
656 mfspr r3, HID0
657 rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
658 blr
659
660 .globl get_pvr
661 get_pvr:
662 mfspr r3, PVR
663 blr
664
665 /*------------------------------------------------------------------------------*/
666
667 /*
668 * void relocate_code (addr_sp, gd, addr_moni)
669 *
670 * This "function" does not return, instead it continues in RAM
671 * after relocating the monitor code.
672 *
673 * r3 = dest
674 * r4 = src
675 * r5 = length in bytes
676 * r6 = cachelinesize
677 */
678 .globl relocate_code
679 relocate_code:
680 mr r1, r3 /* Set new stack pointer */
681 mr r9, r4 /* Save copy of Global Data pointer */
682 mr r10, r5 /* Save copy of Destination Address */
683
684 GET_GOT
685 mr r3, r5 /* Destination Address */
686 lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
687 ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
688 lwz r5, GOT(__init_end)
689 sub r5, r5, r4
690 li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
691
692 /*
693 * Fix GOT pointer:
694 *
695 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
696 *
697 * Offset:
698 */
699 sub r15, r10, r4
700
701 /* First our own GOT */
702 add r12, r12, r15
703 /* then the one used by the C code */
704 add r30, r30, r15
705
706 /*
707 * Now relocate code
708 */
709
710 cmplw cr1,r3,r4
711 addi r0,r5,3
712 srwi. r0,r0,2
713 beq cr1,4f /* In place copy is not necessary */
714 beq 7f /* Protect against 0 count */
715 mtctr r0
716 bge cr1,2f
717
718 la r8,-4(r4)
719 la r7,-4(r3)
720 1: lwzu r0,4(r8)
721 stwu r0,4(r7)
722 bdnz 1b
723 b 4f
724
725 2: slwi r0,r0,2
726 add r8,r4,r0
727 add r7,r3,r0
728 3: lwzu r0,-4(r8)
729 stwu r0,-4(r7)
730 bdnz 3b
731
732 /*
733 * Now flush the cache: note that we must start from a cache aligned
734 * address. Otherwise we might miss one cache line.
735 */
736 4: cmpwi r6,0
737 add r5,r3,r5
738 beq 7f /* Always flush prefetch queue in any case */
739 subi r0,r6,1
740 andc r3,r3,r0
741 mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
742 rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
743 cmpwi r7,0
744 beq 9f
745 mr r4,r3
746 5: dcbst 0,r4
747 add r4,r4,r6
748 cmplw r4,r5
749 blt 5b
750 sync /* Wait for all dcbst to complete on bus */
751 9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
752 rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
753 cmpwi r7,0
754 beq 7f
755 mr r4,r3
756 6: icbi 0,r4
757 add r4,r4,r6
758 cmplw r4,r5
759 blt 6b
760 7: sync /* Wait for all icbi to complete on bus */
761 isync
762
763 /*
764 * We are done. Do not return, instead branch to second part of board
765 * initialization, now running from RAM.
766 */
767
768 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
769 mtlr r0
770 blr
771
772 in_ram:
773
774 /*
775 * Relocation Function, r12 point to got2+0x8000
776 *
777 * Adjust got2 pointers, no need to check for 0, this code
778 * already puts a few entries in the table.
779 */
780 li r0,__got2_entries@sectoff@l
781 la r3,GOT(_GOT2_TABLE_)
782 lwz r11,GOT(_GOT2_TABLE_)
783 mtctr r0
784 sub r11,r3,r11
785 addi r3,r3,-4
786 1: lwzu r0,4(r3)
787 cmpwi r0,0
788 beq- 2f
789 add r0,r0,r11
790 stw r0,0(r3)
791 2: bdnz 1b
792
793 /*
794 * Now adjust the fixups and the pointers to the fixups
795 * in case we need to move ourselves again.
796 */
797 li r0,__fixup_entries@sectoff@l
798 lwz r3,GOT(_FIXUP_TABLE_)
799 cmpwi r0,0
800 mtctr r0
801 addi r3,r3,-4
802 beq 4f
803 3: lwzu r4,4(r3)
804 lwzux r0,r4,r11
805 cmpwi r0,0
806 add r0,r0,r11
807 stw r4,0(r3)
808 beq- 5f
809 stw r0,0(r4)
810 5: bdnz 3b
811 4:
812 clear_bss:
813 /*
814 * Now clear BSS segment
815 */
816 lwz r3,GOT(__bss_start)
817 lwz r4,GOT(__bss_end)
818
819 cmplw 0, r3, r4
820 beq 6f
821
822 li r0, 0
823 5:
824 stw r0, 0(r3)
825 addi r3, r3, 4
826 cmplw 0, r3, r4
827 bne 5b
828 6:
829
830 mr r3, r9 /* Global Data pointer */
831 mr r4, r10 /* Destination Address */
832 bl board_init_r
833
834 /*
835 * Copy exception vector code to low memory
836 *
837 * r3: dest_addr
838 * r7: source address, r8: end address, r9: target address
839 */
840 .globl trap_init
841 trap_init:
842 mflr r4 /* save link register */
843 GET_GOT
844 lwz r7, GOT(_start)
845 lwz r8, GOT(_end_of_vectors)
846
847 li r9, 0x100 /* reset vector always at 0x100 */
848
849 cmplw 0, r7, r8
850 bgelr /* return if r7>=r8 - just in case */
851 1:
852 lwz r0, 0(r7)
853 stw r0, 0(r9)
854 addi r7, r7, 4
855 addi r9, r9, 4
856 cmplw 0, r7, r8
857 bne 1b
858
859 /*
860 * relocate `hdlr' and `int_return' entries
861 */
862 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
863 li r8, Alignment - _start + EXC_OFF_SYS_RESET
864 2:
865 bl trap_reloc
866 addi r7, r7, 0x100 /* next exception vector */
867 cmplw 0, r7, r8
868 blt 2b
869
870 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
871 bl trap_reloc
872
873 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
874 bl trap_reloc
875
876 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
877 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
878 3:
879 bl trap_reloc
880 addi r7, r7, 0x100 /* next exception vector */
881 cmplw 0, r7, r8
882 blt 3b
883
884 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
885 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
886 4:
887 bl trap_reloc
888 addi r7, r7, 0x100 /* next exception vector */
889 cmplw 0, r7, r8
890 blt 4b
891
892 mfmsr r3 /* now that the vectors have */
893 lis r7, MSR_IP@h /* relocated into low memory */
894 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
895 andc r3, r3, r7 /* (if it was on) */
896 SYNC /* Some chip revs need this... */
897 mtmsr r3
898 SYNC
899
900 mtlr r4 /* restore link register */
901 blr