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