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