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