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