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