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