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