]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/start.S
* Get (mostly) rid of CFG_MONITOR_LEN definition; compute real length
[karo-tx-uboot.git] / cpu / ppc4xx / start.S
1 /*
2  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
3  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4  *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24 /*------------------------------------------------------------------------------+ */
25 /* */
26 /*       This source code has been made available to you by IBM on an AS-IS */
27 /*       basis.  Anyone receiving this source is licensed under IBM */
28 /*       copyrights to use it in any way he or she deems fit, including */
29 /*       copying it, modifying it, compiling it, and redistributing it either */
30 /*       with or without modifications.  No license under IBM patents or */
31 /*       patent applications is to be implied by the copyright license. */
32 /* */
33 /*       Any user of this software should understand that IBM cannot provide */
34 /*       technical support for this software and will not be responsible for */
35 /*       any consequences resulting from the use of this software. */
36 /* */
37 /*       Any person who transfers this source code or any derivative work */
38 /*       must include the IBM copyright notice, this paragraph, and the */
39 /*       preceding two paragraphs in the transferred software. */
40 /* */
41 /*       COPYRIGHT   I B M   CORPORATION 1995 */
42 /*       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M */
43 /*------------------------------------------------------------------------------- */
44
45 /*  U-Boot - Startup Code for IBM 4xx PowerPC based Embedded Boards
46  *
47  *
48  *  The processor starts at 0xfffffffc and the code is executed
49  *  from flash/rom.
50  *  in memory, but as long we don't jump around before relocating.
51  *  board_init lies at a quite high address and when the cpu has
52  *  jumped there, everything is ok.
53  *  This works because the cpu gives the FLASH (CS0) the whole
54  *  address space at startup, and board_init lies as a echo of
55  *  the flash somewhere up there in the memorymap.
56  *
57  *  board_init will change CS0 to be positioned at the correct
58  *  address and (s)dram will be positioned at address 0
59  */
60 #include <config.h>
61 #include <mpc8xx.h>
62 #include <ppc4xx.h>
63 #include <version.h>
64
65 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
66
67 #include <ppc_asm.tmpl>
68 #include <ppc_defs.h>
69
70 #include <asm/cache.h>
71 #include <asm/mmu.h>
72
73 #ifndef  CONFIG_IDENT_STRING
74 #define  CONFIG_IDENT_STRING ""
75 #endif
76
77 #ifdef CFG_INIT_DCACHE_CS
78 # if (CFG_INIT_DCACHE_CS == 0)
79 #  define PBxAP pb0ap
80 #  define PBxCR pb0cr
81 # endif
82 # if (CFG_INIT_DCACHE_CS == 1)
83 #  define PBxAP pb1ap
84 #  define PBxCR pb1cr
85 # endif
86 # if (CFG_INIT_DCACHE_CS == 2)
87 #  define PBxAP pb2ap
88 #  define PBxCR pb2cr
89 # endif
90 # if (CFG_INIT_DCACHE_CS == 3)
91 #  define PBxAP pb3ap
92 #  define PBxCR pb3cr
93 # endif
94 # if (CFG_INIT_DCACHE_CS == 4)
95 #  define PBxAP pb4ap
96 #  define PBxCR pb4cr
97 # endif
98 # if (CFG_INIT_DCACHE_CS == 5)
99 #  define PBxAP pb5ap
100 #  define PBxCR pb5cr
101 # endif
102 # if (CFG_INIT_DCACHE_CS == 6)
103 #  define PBxAP pb6ap
104 #  define PBxCR pb6cr
105 # endif
106 # if (CFG_INIT_DCACHE_CS == 7)
107 #  define PBxAP pb7ap
108 #  define PBxCR pb7cr
109 # endif
110 #endif /* CFG_INIT_DCACHE_CS */
111
112 /* We don't want the  MMU yet.
113 */
114 #undef  MSR_KERNEL
115 #define MSR_KERNEL ( MSR_ME  )  /* Machine Check */
116
117
118         .extern ext_bus_cntlr_init
119         .extern sdram_init
120
121 /*
122  * Set up GOT: Global Offset Table
123  *
124  * Use r14 to access the GOT
125  */
126         START_GOT
127         GOT_ENTRY(_GOT2_TABLE_)
128         GOT_ENTRY(_FIXUP_TABLE_)
129
130         GOT_ENTRY(_start)
131         GOT_ENTRY(_start_of_vectors)
132         GOT_ENTRY(_end_of_vectors)
133         GOT_ENTRY(transfer_to_handler)
134
135         GOT_ENTRY(__init_end)
136         GOT_ENTRY(_end)
137         GOT_ENTRY(__bss_start)
138         END_GOT
139
140 /*
141  * 440 Startup -- on reset only the top 4k of the effective
142  * address space is mapped in by an entry in the instruction
143  * and data shadow TLB. The .bootpg section is located in the
144  * top 4k & does only what's necessary to map in the the rest
145  * of the boot rom. Once the boot rom is mapped in we can
146  * proceed with normal startup.
147  *
148  * NOTE: CS0 only covers the top 2MB of the effective address
149  * space after reset.
150  */
151
152 #if defined(CONFIG_440)
153     .section .bootpg,"ax"
154     .globl _start_440
155
156 /**************************************************************************/
157 _start_440:
158         /*----------------------------------------------------------------*/
159         /* Clear and set up some registers. */
160         /*----------------------------------------------------------------*/
161         iccci   r0,r0           /* NOTE: operands not used for 440 */
162         dccci   r0,r0           /* NOTE: operands not used for 440 */
163         sync
164         li      r0,0
165         mtspr   srr0,r0
166         mtspr   srr1,r0
167         mtspr   csrr0,r0
168         mtspr   csrr1,r0
169
170         /*----------------------------------------------------------------*/
171         /* Initialize debug */
172         /*----------------------------------------------------------------*/
173         mtspr   dbcr0,r0
174         mtspr   dbcr1,r0
175         mtspr   dbcr2,r0
176         mtspr   iac1,r0
177         mtspr   iac2,r0
178         mtspr   iac3,r0
179         mtspr   dac1,r0
180         mtspr   dac2,r0
181         mtspr   dvc1,r0
182         mtspr   dvc2,r0
183
184         mfspr   r1,dbsr
185         mtspr   dbsr,r1         /* Clear all valid bits */
186
187         /*----------------------------------------------------------------*/
188         /* CCR0 init */
189         /*----------------------------------------------------------------*/
190         /* Disable store gathering & broadcast, guarantee inst/data
191         * cache block touch, force load/store alignment
192         * (see errata 1.12: 440_33)
193         */
194         lis     r1,0x0030       /* store gathering & broadcast disable */
195         ori     r1,r1,0x6000    /* cache touch */
196         mtspr   ccr0,r1
197
198         /*----------------------------------------------------------------*/
199         /* Setup interrupt vectors */
200         /*----------------------------------------------------------------*/
201         mtspr   ivpr,r0         /* Vectors start at 0x0000_0000 */
202         li      r1,0x0100
203         mtspr   ivor0,r1        /* Critical input */
204         li      r1,0x0200
205         mtspr   ivor1,r1        /* Machine check */
206         li      r1,0x0300
207         mtspr   ivor2,r1        /* Data storage */
208         li      r1,0x0400
209         mtspr   ivor3,r1        /* Instruction storage */
210         li      r1,0x0500
211         mtspr   ivor4,r1        /* External interrupt */
212         li      r1,0x0600
213         mtspr   ivor5,r1        /* Alignment */
214         li      r1,0x0700
215         mtspr   ivor6,r1        /* Program check */
216         li      r1,0x0800
217         mtspr   ivor7,r1        /* Floating point unavailable */
218         li      r1,0x0c00
219         mtspr   ivor8,r1        /* System call */
220         li      r1,0x1000
221         mtspr   ivor10,r1       /* Decrementer (PIT for 440) */
222         li      r1,0x1400
223         mtspr   ivor13,r1       /* Data TLB error */
224         li      r1,0x1300
225         mtspr   ivor14,r1       /* Instr TLB error */
226         li      r1,0x2000
227         mtspr   ivor15,r1       /* Debug */
228
229         /*----------------------------------------------------------------*/
230         /* Configure cache regions  */
231         /*----------------------------------------------------------------*/
232         mtspr   inv0,r0
233         mtspr   inv1,r0
234         mtspr   inv2,r0
235         mtspr   inv3,r0
236         mtspr   dnv0,r0
237         mtspr   dnv1,r0
238         mtspr   dnv2,r0
239         mtspr   dnv3,r0
240         mtspr   itv0,r0
241         mtspr   itv1,r0
242         mtspr   itv2,r0
243         mtspr   itv3,r0
244         mtspr   dtv0,r0
245         mtspr   dtv1,r0
246         mtspr   dtv2,r0
247         mtspr   dtv3,r0
248
249         /*----------------------------------------------------------------*/
250         /* Cache victim limits */
251         /*----------------------------------------------------------------*/
252         /* floors 0, ceiling max to use the entire cache -- nothing locked
253         */
254         lis     r1,0x0001
255         ori     r1,r1,0xf800
256         mtspr   ivlim,r1
257         mtspr   dvlim,r1
258
259         /*----------------------------------------------------------------*/
260         /* Clear all TLB entries -- TID = 0, TS = 0 */
261         /*----------------------------------------------------------------*/
262         mtspr   mmucr,r0
263         li      r1,0x003f       /* 64 TLB entries */
264         mtctr   r1
265 0:      tlbwe   r0,r1,0x0000    /* Invalidate all entries (V=0)*/
266         subi    r1,r1,0x0001
267         bdnz    0b
268
269         /*----------------------------------------------------------------*/
270         /* TLB entry setup -- step thru tlbtab */
271         /*----------------------------------------------------------------*/
272         bl      tlbtab          /* Get tlbtab pointer */
273         mr      r5,r0
274         li      r1,0x003f       /* 64 TLB entries max */
275         mtctr   r1
276         li      r4,0            /* TLB # */
277
278         addi    r5,r5,-4
279 1:      lwzu    r0,4(r5)
280         cmpwi   r0,0
281         beq     2f              /* 0 marks end */
282         lwzu    r1,4(r5)
283         lwzu    r2,4(r5)
284         tlbwe   r0,r4,0         /* TLB Word 0 */
285         tlbwe   r1,r4,1         /* TLB Word 1 */
286         tlbwe   r2,r4,2         /* TLB Word 2 */
287         addi    r4,r4,1         /* Next TLB */
288         bdnz    1b
289
290         /*----------------------------------------------------------------*/
291         /* Continue from 'normal' start */
292         /*----------------------------------------------------------------*/
293 2:      bl      3f
294         b       _start
295
296 3:      li      r0,0
297         mtspr   srr1,r0         /* Keep things disabled for now */
298         mflr    r1
299         mtspr   srr0,r1
300         rfi
301 #endif /* CONFIG_440 */
302
303 /*
304  * r3 - 1st arg to board_init(): IMMP pointer
305  * r4 - 2nd arg to board_init(): boot flag
306  */
307         .text
308         .long   0x27051956              /* U-Boot Magic Number                  */
309         .globl  version_string
310 version_string:
311         .ascii U_BOOT_VERSION
312         .ascii " (", __DATE__, " - ", __TIME__, ")"
313         .ascii CONFIG_IDENT_STRING, "\0"
314
315 /*
316  * Maybe this should be moved somewhere else because the current
317  * location (0x100) is where the CriticalInput Execption should be.
318  */
319         . = EXC_OFF_SYS_RESET
320         .globl  _start
321 _start:
322
323 /*****************************************************************************/
324 #if defined(CONFIG_440)
325
326         /*----------------------------------------------------------------*/
327         /* Clear and set up some registers. */
328         /*----------------------------------------------------------------*/
329         li      r0,0x0000
330         lis     r1,0xffff
331         mtspr   dec,r0                  /* prevent dec exceptions */
332         mtspr   tbl,r0                  /* prevent fit & wdt exceptions */
333         mtspr   tbu,r0
334         mtspr   tsr,r1                  /* clear all timer exception status */
335         mtspr   tcr,r0                  /* disable all */
336         mtspr   esr,r0                  /* clear exception syndrome register */
337         mtxer   r0                      /* clear integer exception register */
338         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
339         ori     r1,r1,0x1000            /* set ME bit (Machine Exceptions) */
340         mtmsr   r1                      /* change MSR */
341
342         /*----------------------------------------------------------------*/
343         /* Debug setup -- some (not very good) ice's need an event*/
344         /* to establish control :-( Define CFG_INIT_DBCR to the dbsr */
345         /* value you need in this case 0x8cff 0000 should do the trick */
346         /*----------------------------------------------------------------*/
347 #if defined(CFG_INIT_DBCR)
348         lis     r1,0xffff
349         ori     r1,r1,0xffff
350         mtspr   dbsr,r1                 /* Clear all status bits */
351         lis     r0,CFG_INIT_DBCR@h
352         ori     r0,r0,CFG_INIT_DBCR@l
353         mtspr   dbcr0,r0
354         isync
355 #endif
356
357         /*----------------------------------------------------------------*/
358         /* Setup the internal SRAM */
359         /*----------------------------------------------------------------*/
360         li      r0,0
361         mtdcr   isram0_sb1cr,r0         /* Disable bank 1 */
362
363         li      r2,0x7fff
364         ori     r2,r2,0xffff
365         mfdcr   r1,isram0_dpc
366         and     r1,r1,r2                /* Disable parity check */
367         mtdcr   isram0_dpc,r1
368         mfdcr   r1,isram0_pmeg
369         andis.  r1,r1,r2                /* Disable pwr mgmt */
370         mtdcr   isram0_pmeg,r1
371
372         lis     r1,0x8000               /* BAS = 8000_0000 */
373         ori     r1,r1,0x0380            /* 8k rw */
374         mtdcr   isram0_sb0cr,r1
375
376         /*----------------------------------------------------------------*/
377         /* Setup the stack in internal SRAM */
378         /*----------------------------------------------------------------*/
379         lis     r1,CFG_INIT_RAM_ADDR@h
380         ori     r1,r1,CFG_INIT_SP_OFFSET@l
381
382         li      r0,0
383         stwu    r0,-4(r1)
384         stwu    r0,-4(r1)               /* Terminate call chain */
385
386         stwu    r1,-8(r1)               /* Save back chain and move SP */
387         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
388         ori     r0,r0, RESET_VECTOR@l
389         stwu    r1,-8(r1)               /* Save back chain and move SP */
390         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
391
392         GET_GOT
393         bl      board_init_f
394
395 #endif /* CONFIG_440 */
396
397 /*****************************************************************************/
398 #ifdef CONFIG_IOP480
399         /*----------------------------------------------------------------------- */
400         /* Set up some machine state registers. */
401         /*----------------------------------------------------------------------- */
402         addi    r0,r0,0x0000            /* initialize r0 to zero */
403         mtspr   esr,r0                  /* clear Exception Syndrome Reg */
404         mttcr   r0                      /* timer control register */
405         mtexier r0                      /* disable all interrupts */
406         addi    r4,r0,0x1000            /* set ME bit (Machine Exceptions) */
407         oris    r4,r4,0x2               /* set CE bit (Critical Exceptions) */
408         mtmsr   r4                      /* change MSR */
409         addis   r4,r0,0xFFFF            /* set r4 to 0xFFFFFFFF (status in the */
410         ori     r4,r4,0xFFFF            /* dbsr is cleared by setting bits to 1) */
411         mtdbsr  r4                      /* clear/reset the dbsr */
412         mtexisr r4                      /* clear all pending interrupts */
413         addis   r4,r0,0x8000
414         mtexier r4                      /* enable critical exceptions */
415         addis   r4,r0,0x0000            /* assume 403GCX - enable core clk */
416         ori     r4,r4,0x4020            /* dbling (no harm done on GA and GC */
417         mtiocr  r4                      /* since bit not used) & DRC to latch */
418                                         /* data bus on rising edge of CAS */
419         /*----------------------------------------------------------------------- */
420         /* Clear XER. */
421         /*----------------------------------------------------------------------- */
422         mtxer   r0
423         /*----------------------------------------------------------------------- */
424         /* Invalidate i-cache and d-cache TAG arrays. */
425         /*----------------------------------------------------------------------- */
426         addi    r3,0,1024               /* 1/4 of I-cache size, half of D-cache */
427         addi    r4,0,1024               /* 1/4 of I-cache */
428 ..cloop:
429         iccci   0,r3
430         iccci   r4,r3
431         dccci   0,r3
432         addic.  r3,r3,-16               /* move back one cache line */
433         bne     ..cloop                 /* loop back to do rest until r3 = 0 */
434
435         /* */
436         /* initialize IOP480 so it can read 1 MB code area for SRAM spaces */
437         /* this requires enabling MA[17..0], by default only MA[12..0] are enabled. */
438         /* */
439
440         /* first copy IOP480 register base address into r3 */
441         addis   r3,0,0x5000             /* IOP480 register base address hi */
442 /*      ori     r3,r3,0x0000            /  IOP480 register base address lo */
443
444 #ifdef CONFIG_ADCIOP
445         /* use r4 as the working variable */
446         /* turn on CS3 (LOCCTL.7) */
447         lwz     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
448         andi.   r4,r4,0xff7f            /* make bit 7 = 0 -- CS3 mode */
449         stw     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
450 #endif
451
452 #ifdef CONFIG_DASA_SIM
453         /* use r4 as the working variable */
454         /* turn on MA17 (LOCCTL.7) */
455         lwz     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
456         ori     r4,r4,0x80              /* make bit 7 = 1 -- MA17 mode */
457         stw     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
458 #endif
459
460         /* turn on MA16..13 (LCS0BRD.12 = 0) */
461         lwz     r4,0x100(r3)            /* LCS0BRD is at offset 0x100 */
462         andi.   r4,r4,0xefff            /* make bit 12 = 0 */
463         stw     r4,0x100(r3)            /* LCS0BRD is at offset 0x100 */
464
465         /* make sure above stores all comlete before going on */
466         sync
467
468         /* last thing, set local init status done bit (DEVINIT.31) */
469         lwz     r4,0x80(r3)             /* DEVINIT is at offset 0x80 */
470         oris    r4,r4,0x8000            /* make bit 31 = 1 */
471         stw     r4,0x80(r3)             /* DEVINIT is at offset 0x80 */
472
473         /* clear all pending interrupts and disable all interrupts */
474         li      r4,-1                   /* set p1 to 0xffffffff */
475         stw     r4,0x1b0(r3)            /* clear all pending interrupts */
476         stw     r4,0x1b8(r3)            /* clear all pending interrupts */
477         li      r4,0                    /* set r4 to 0 */
478         stw     r4,0x1b4(r3)            /* disable all interrupts */
479         stw     r4,0x1bc(r3)            /* disable all interrupts */
480
481         /* make sure above stores all comlete before going on */
482         sync
483
484         /*----------------------------------------------------------------------- */
485         /* Enable two 128MB cachable regions. */
486         /*----------------------------------------------------------------------- */
487         addis   r1,r0,0x8000
488         addi    r1,r1,0x0001
489         mticcr  r1                      /* instruction cache */
490
491         addis   r1,r0,0x0000
492         addi    r1,r1,0x0000
493         mtdccr  r1                      /* data cache */
494
495         addis   r1,r0,CFG_INIT_RAM_ADDR@h
496         ori     r1,r1,CFG_INIT_SP_OFFSET          /* set up the stack to SDRAM */
497         li      r0, 0                   /* Make room for stack frame header and */
498         stwu    r0, -4(r1)              /* clear final stack frame so that      */
499         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
500
501         GET_GOT                 /* initialize GOT access                        */
502
503         bl      board_init_f    /* run first part of init code (from Flash)     */
504
505 #endif  /* CONFIG_IOP480 */
506
507 /*****************************************************************************/
508 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_405EP)
509         /*----------------------------------------------------------------------- */
510         /* Clear and set up some registers. */
511         /*----------------------------------------------------------------------- */
512         addi    r4,r0,0x0000
513         mtspr   sgr,r4
514         mtspr   dcwr,r4
515         mtesr   r4                      /* clear Exception Syndrome Reg */
516         mttcr   r4                      /* clear Timer Control Reg */
517         mtxer   r4                      /* clear Fixed-Point Exception Reg */
518         mtevpr  r4                      /* clear Exception Vector Prefix Reg */
519         addi    r4,r0,0x1000            /* set ME bit (Machine Exceptions) */
520         oris    r4,r4,0x0002            /* set CE bit (Critical Exceptions) */
521         mtmsr   r4                      /* change MSR */
522         addi    r4,r0,(0xFFFF-0x10000)          /* set r4 to 0xFFFFFFFF (status in the */
523                                         /* dbsr is cleared by setting bits to 1) */
524         mtdbsr  r4                      /* clear/reset the dbsr */
525
526         /*----------------------------------------------------------------------- */
527         /* Invalidate I and D caches. Enable I cache for defined memory regions */
528         /* to speed things up. Leave the D cache disabled for now. It will be */
529         /* enabled/left disabled later based on user selected menu options. */
530         /* Be aware that the I cache may be disabled later based on the menu */
531         /* options as well. See miscLib/main.c. */
532         /*----------------------------------------------------------------------- */
533         bl      invalidate_icache
534         bl      invalidate_dcache
535
536         /*----------------------------------------------------------------------- */
537         /* Enable two 128MB cachable regions. */
538         /*----------------------------------------------------------------------- */
539         addis   r4,r0,0x8000
540         addi    r4,r4,0x0001
541         mticcr  r4                      /* instruction cache */
542         isync
543
544         addis   r4,r0,0x0000
545         addi    r4,r4,0x0000
546         mtdccr  r4                      /* data cache */
547
548 #if !(defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
549         /*----------------------------------------------------------------------- */
550         /* Tune the speed and size for flash CS0  */
551         /*----------------------------------------------------------------------- */
552         bl      ext_bus_cntlr_init
553 #endif
554
555 #if defined(CONFIG_405EP)
556         /*----------------------------------------------------------------------- */
557         /* DMA Status, clear to come up clean */
558         /*----------------------------------------------------------------------- */
559         addis   r3,r0, 0xFFFF         /* Clear all existing DMA status */
560         ori     r3,r3, 0xFFFF
561         mtdcr   dmasr, r3
562
563         bl      ppc405ep_init         /* do ppc405ep specific init */
564 #endif /* CONFIG_405EP */
565
566 #if defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE)
567         /********************************************************************
568          * Setup OCM - On Chip Memory
569          *******************************************************************/
570         /* Setup OCM */
571         lis     r0, 0x7FFF
572         ori     r0, r0, 0xFFFF
573         mfdcr   r3, ocmiscntl           /* get instr-side IRAM config */
574         mfdcr   r4, ocmdscntl   /* get data-side IRAM config */
575         and     r3, r3, r0      /* disable data-side IRAM */
576         and     r4, r4, r0      /* disable data-side IRAM */
577         mtdcr   ocmiscntl, r3   /* set instr-side IRAM config */
578         mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
579         isync
580
581         addis   r3, 0, CFG_OCM_DATA_ADDR@h /* OCM location */
582         mtdcr   ocmdsarc, r3
583         addis   r4, 0, 0xC000           /* OCM data area enabled */
584         mtdcr   ocmdscntl, r4
585         isync
586 #endif
587
588         /*----------------------------------------------------------------------- */
589         /* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */
590         /*----------------------------------------------------------------------- */
591 #ifdef CFG_INIT_DCACHE_CS
592         /*----------------------------------------------------------------------- */
593         /* Memory Bank x (nothingness) initialization 1GB+64MEG */
594         /* used as temporary stack pointer for stage0  */
595         /*----------------------------------------------------------------------- */
596         li      r4,PBxAP
597         mtdcr   ebccfga,r4
598         lis     r4,0x0380
599         ori     r4,r4,0x0480
600         mtdcr   ebccfgd,r4
601
602         addi    r4,0,PBxCR
603         mtdcr   ebccfga,r4
604         lis     r4,0x400D
605         ori     r4,r4,0xa000
606         mtdcr   ebccfgd,r4
607
608         /* turn on data chache for this region */
609         lis     r4,0x0080
610         mtdccr  r4
611
612         /* set stack pointer and clear stack to known value */
613
614         lis     r1,CFG_INIT_RAM_ADDR@h
615         ori     r1,r1,CFG_INIT_SP_OFFSET@l
616
617         li      r4,2048                 /* we store 2048 words to stack */
618         mtctr   r4
619
620         lis     r2,CFG_INIT_RAM_ADDR@h          /* we also clear data area */
621         ori     r2,r2,CFG_INIT_RAM_END@l        /* so cant copy value from r1 */
622
623         lis     r4,0xdead               /* we store 0xdeaddead in the stack */
624         ori     r4,r4,0xdead
625
626 ..stackloop:
627         stwu    r4,-4(r2)
628         bdnz    ..stackloop
629
630         li      r0, 0                   /* Make room for stack frame header and */
631         stwu    r0, -4(r1)              /* clear final stack frame so that      */
632         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
633         /*
634          * Set up a dummy frame to store reset vector as return address.
635          * this causes stack underflow to reset board.
636          */
637         stwu    r1, -8(r1)              /* Save back chain and move SP */
638         addis   r0, 0, RESET_VECTOR@h   /* Address of reset vector */
639         ori     r0, r0, RESET_VECTOR@l
640         stwu    r1, -8(r1)              /* Save back chain and move SP */
641         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
642
643 #elif defined(CFG_TEMP_STACK_OCM) && \
644         (defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE))
645         /*
646          * Stack in OCM.
647          */
648
649         /* Set up Stack at top of OCM */
650         lis     r1, (CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET)@h
651         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET)@l
652
653         /* Set up a zeroized stack frame so that backtrace works right */
654         li      r0, 0
655         stwu    r0, -4(r1)
656         stwu    r0, -4(r1)
657
658         /*
659          * Set up a dummy frame to store reset vector as return address.
660          * this causes stack underflow to reset board.
661          */
662         stwu    r1, -8(r1)              /* Save back chain and move SP */
663         lis     r0, RESET_VECTOR@h      /* Address of reset vector */
664         ori     r0, r0, RESET_VECTOR@l
665         stwu    r1, -8(r1)              /* Save back chain and move SP */
666         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
667 #endif /* CFG_INIT_DCACHE_CS */
668
669         /*----------------------------------------------------------------------- */
670         /* Initialize SDRAM Controller  */
671         /*----------------------------------------------------------------------- */
672         bl      sdram_init
673
674         /*
675          * Setup temporary stack pointer only for boards
676          * that do not use SDRAM SPD I2C stuff since it
677          * is already initialized to use DCACHE or OCM
678          * stacks.
679          */
680 #if !(defined(CFG_INIT_DCACHE_CS) || defined(CFG_TEMP_STACK_OCM))
681         lis     r1, CFG_INIT_RAM_ADDR@h
682         ori     r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */
683
684         li      r0, 0                   /* Make room for stack frame header and */
685         stwu    r0, -4(r1)              /* clear final stack frame so that      */
686         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
687         /*
688          * Set up a dummy frame to store reset vector as return address.
689          * this causes stack underflow to reset board.
690          */
691         stwu    r1, -8(r1)              /* Save back chain and move SP */
692         lis     r0, RESET_VECTOR@h      /* Address of reset vector */
693         ori     r0, r0, RESET_VECTOR@l
694         stwu    r1, -8(r1)              /* Save back chain and move SP */
695         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
696 #endif /* !(CFG_INIT_DCACHE_CS  || !CFG_TEM_STACK_OCM) */
697
698         GET_GOT                 /* initialize GOT access                        */
699
700         bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
701
702         /* NEVER RETURNS! */
703         bl      board_init_f    /* run first part of init code (from Flash)     */
704
705 #endif  /* CONFIG_405GP || CONFIG_405CR */
706
707
708 /*****************************************************************************/
709         .globl  _start_of_vectors
710 _start_of_vectors:
711
712 #if 0
713 /*TODO Fixup _start above so we can do this*/
714 /* Critical input. */
715         CRIT_EXCEPTION(0x100, CritcalInput, CritcalInputException)
716 #endif
717
718 /* Machine check */
719         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
720
721 /* Data Storage exception. */
722         STD_EXCEPTION(0x300, DataStorage, UnknownException)
723
724 /* Instruction Storage exception. */
725         STD_EXCEPTION(0x400, InstStorage, UnknownException)
726
727 /* External Interrupt exception. */
728         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
729
730 /* Alignment exception. */
731         . = 0x600
732 Alignment:
733         EXCEPTION_PROLOG
734         mfspr   r4,DAR
735         stw     r4,_DAR(r21)
736         mfspr   r5,DSISR
737         stw     r5,_DSISR(r21)
738         addi    r3,r1,STACK_FRAME_OVERHEAD
739         li      r20,MSR_KERNEL
740         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
741         lwz     r6,GOT(transfer_to_handler)
742         mtlr    r6
743         blrl
744 .L_Alignment:
745         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
746         .long   int_return - _start + EXC_OFF_SYS_RESET
747
748 /* Program check exception */
749         . = 0x700
750 ProgramCheck:
751         EXCEPTION_PROLOG
752         addi    r3,r1,STACK_FRAME_OVERHEAD
753         li      r20,MSR_KERNEL
754         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
755         lwz     r6,GOT(transfer_to_handler)
756         mtlr    r6
757         blrl
758 .L_ProgramCheck:
759         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
760         .long   int_return - _start + EXC_OFF_SYS_RESET
761
762         /* No FPU on MPC8xx.  This exception is not supposed to happen.
763         */
764         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
765
766         /* I guess we could implement decrementer, and may have
767          * to someday for timekeeping.
768          */
769         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
770         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
771         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
772
773         . = 0xc00
774 /*
775  * r0 - SYSCALL number
776  * r3-... arguments
777  */
778 SystemCall:
779         addis   r11,r0,0                /* get functions table addr */
780         ori     r11,r11,0               /* Note: this code is patched in trap_init */
781         addis   r12,r0,0                /* get number of functions */
782         ori     r12,r12,0
783
784         cmplw   0, r0, r12
785         bge     1f
786
787         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
788         add     r11,r11,r0
789         lwz     r11,0(r11)
790
791         li      r20,0xd00-4             /* Get stack pointer */
792         lwz     r12,0(r20)
793         subi    r12,r12,12              /* Adjust stack pointer */
794         li      r0,0xc00+_end_back-SystemCall
795         cmplw   0, r0, r12              /* Check stack overflow */
796         bgt     1f
797         stw     r12,0(r20)
798
799         mflr    r0
800         stw     r0,0(r12)
801         mfspr   r0,SRR0
802         stw     r0,4(r12)
803         mfspr   r0,SRR1
804         stw     r0,8(r12)
805
806         li      r12,0xc00+_back-SystemCall
807         mtlr    r12
808         mtspr   SRR0,r11
809
810 1:      SYNC
811         rfi
812
813 _back:
814
815         mfmsr   r11                     /* Disable interrupts */
816         li      r12,0
817         ori     r12,r12,MSR_EE
818         andc    r11,r11,r12
819         SYNC                            /* Some chip revs need this... */
820         mtmsr   r11
821         SYNC
822
823         li      r12,0xd00-4             /* restore regs */
824         lwz     r12,0(r12)
825
826         lwz     r11,0(r12)
827         mtlr    r11
828         lwz     r11,4(r12)
829         mtspr   SRR0,r11
830         lwz     r11,8(r12)
831         mtspr   SRR1,r11
832
833         addi    r12,r12,12              /* Adjust stack pointer */
834         li      r20,0xd00-4
835         stw     r12,0(r20)
836
837         SYNC
838         rfi
839 _end_back:
840
841         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
842
843         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
844         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
845
846         /* On the MPC8xx, this is a software emulation interrupt.  It occurs
847          * for all unimplemented and illegal instructions.
848          */
849         STD_EXCEPTION(0x1000, PIT, PITException)
850
851         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
852         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
853         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
854         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
855
856         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
857         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
858         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
859         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
860         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
861         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
862         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
863
864         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
865         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
866         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
867         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
868
869         CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
870
871         .globl  _end_of_vectors
872 _end_of_vectors:
873
874
875         . = 0x2100
876
877 /*
878  * This code finishes saving the registers to the exception frame
879  * and jumps to the appropriate handler for the exception.
880  * Register r21 is pointer into trap frame, r1 has new stack pointer.
881  */
882         .globl  transfer_to_handler
883 transfer_to_handler:
884         stw     r22,_NIP(r21)
885         lis     r22,MSR_POW@h
886         andc    r23,r23,r22
887         stw     r23,_MSR(r21)
888         SAVE_GPR(7, r21)
889         SAVE_4GPRS(8, r21)
890         SAVE_8GPRS(12, r21)
891         SAVE_8GPRS(24, r21)
892 #if 0
893         andi.   r23,r23,MSR_PR
894         mfspr   r23,SPRG3               /* if from user, fix up tss.regs */
895         beq     2f
896         addi    r24,r1,STACK_FRAME_OVERHEAD
897         stw     r24,PT_REGS(r23)
898 2:      addi    r2,r23,-TSS             /* set r2 to current */
899         tovirt(r2,r2,r23)
900 #endif
901         mflr    r23
902         andi.   r24,r23,0x3f00          /* get vector offset */
903         stw     r24,TRAP(r21)
904         li      r22,0
905         stw     r22,RESULT(r21)
906         mtspr   SPRG2,r22               /* r1 is now kernel sp */
907 #if 0
908         addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
909         cmplw   0,r1,r2
910         cmplw   1,r1,r24
911         crand   1,1,4
912         bgt     stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
913 #endif
914         lwz     r24,0(r23)              /* virtual address of handler */
915         lwz     r23,4(r23)              /* where to go when done */
916         mtspr   SRR0,r24
917         mtspr   SRR1,r20
918         mtlr    r23
919         SYNC
920         rfi                             /* jump to handler, enable MMU */
921
922 int_return:
923         mfmsr   r28             /* Disable interrupts */
924         li      r4,0
925         ori     r4,r4,MSR_EE
926         andc    r28,r28,r4
927         SYNC                    /* Some chip revs need this... */
928         mtmsr   r28
929         SYNC
930         lwz     r2,_CTR(r1)
931         lwz     r0,_LINK(r1)
932         mtctr   r2
933         mtlr    r0
934         lwz     r2,_XER(r1)
935         lwz     r0,_CCR(r1)
936         mtspr   XER,r2
937         mtcrf   0xFF,r0
938         REST_10GPRS(3, r1)
939         REST_10GPRS(13, r1)
940         REST_8GPRS(23, r1)
941         REST_GPR(31, r1)
942         lwz     r2,_NIP(r1)     /* Restore environment */
943         lwz     r0,_MSR(r1)
944         mtspr   SRR0,r2
945         mtspr   SRR1,r0
946         lwz     r0,GPR0(r1)
947         lwz     r2,GPR2(r1)
948         lwz     r1,GPR1(r1)
949         SYNC
950         rfi
951
952 crit_return:
953         mfmsr   r28             /* Disable interrupts */
954         li      r4,0
955         ori     r4,r4,MSR_EE
956         andc    r28,r28,r4
957         SYNC                    /* Some chip revs need this... */
958         mtmsr   r28
959         SYNC
960         lwz     r2,_CTR(r1)
961         lwz     r0,_LINK(r1)
962         mtctr   r2
963         mtlr    r0
964         lwz     r2,_XER(r1)
965         lwz     r0,_CCR(r1)
966         mtspr   XER,r2
967         mtcrf   0xFF,r0
968         REST_10GPRS(3, r1)
969         REST_10GPRS(13, r1)
970         REST_8GPRS(23, r1)
971         REST_GPR(31, r1)
972         lwz     r2,_NIP(r1)     /* Restore environment */
973         lwz     r0,_MSR(r1)
974         mtspr   990,r2          /* SRR2 */
975         mtspr   991,r0          /* SRR3 */
976         lwz     r0,GPR0(r1)
977         lwz     r2,GPR2(r1)
978         lwz     r1,GPR1(r1)
979         SYNC
980         rfci
981
982 /* Cache functions.
983 */
984 invalidate_icache:
985         iccci   r0,r0                   /* for 405, iccci invalidates the */
986         blr                             /*   entire I cache */
987
988 invalidate_dcache:
989         addi    r6,0,0x0000             /* clear GPR 6 */
990         /* Do loop for # of dcache congruence classes. */
991         addi    r7,r0, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
992                                         /* NOTE: dccci invalidates both */
993         mtctr   r7                      /* ways in the D cache */
994 ..dcloop:
995         dccci   0,r6                    /* invalidate line */
996         addi    r6,r6, CFG_CACHELINE_SIZE /* bump to next line */
997         bdnz    ..dcloop
998         blr
999
1000 flush_dcache:
1001         addis   r9,r0,0x0002            /* set mask for EE and CE msr bits */
1002         ori     r9,r9,0x8000
1003         mfmsr   r12                     /* save msr */
1004         andc    r9,r12,r9
1005         mtmsr   r9                      /* disable EE and CE */
1006         addi    r10,r0,0x0001           /* enable data cache for unused memory */
1007         mfdccr  r9                      /* region 0xF8000000-0xFFFFFFFF via */
1008         or      r10,r10,r9              /* bit 31 in dccr */
1009         mtdccr  r10
1010
1011         /* do loop for # of congruence classes. */
1012         addi    r10,r0,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
1013         addi    r11,r0,(CFG_DCACHE_SIZE / 2) /* D cache set size - 2 way sets */
1014         mtctr   r10
1015         addi    r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */
1016         add     r11,r10,r11             /* add to get to other side of cache line */
1017 ..flush_dcache_loop:
1018         lwz     r3,0(r10)               /* least recently used side */
1019         lwz     r3,0(r11)               /* the other side */
1020         dccci   r0,r11                  /* invalidate both sides */
1021         addi    r10,r10,CFG_CACHELINE_SIZE /* bump to next line */
1022         addi    r11,r11,CFG_CACHELINE_SIZE /* bump to next line */
1023         bdnz    ..flush_dcache_loop
1024         sync                            /* allow memory access to complete */
1025         mtdccr  r9                      /* restore dccr */
1026         mtmsr   r12                     /* restore msr */
1027         blr
1028
1029         .globl  icache_enable
1030 icache_enable:
1031         mflr    r8
1032         bl      invalidate_icache
1033         mtlr    r8
1034         isync
1035         addis   r3,r0, 0x8000         /* set bit 0 */
1036         mticcr  r3
1037         blr
1038
1039         .globl  icache_disable
1040 icache_disable:
1041         addis   r3,r0, 0x0000         /* clear bit 0 */
1042         mticcr  r3
1043         isync
1044         blr
1045
1046         .globl  icache_status
1047 icache_status:
1048         mficcr  r3
1049         srwi    r3, r3, 31      /* >>31 => select bit 0 */
1050         blr
1051
1052         .globl  dcache_enable
1053 dcache_enable:
1054         mflr    r8
1055         bl      invalidate_dcache
1056         mtlr    r8
1057         isync
1058         addis   r3,r0, 0x8000         /* set bit 0 */
1059         mtdccr  r3
1060         blr
1061
1062         .globl  dcache_disable
1063 dcache_disable:
1064         mflr    r8
1065         bl      flush_dcache
1066         mtlr    r8
1067         addis   r3,r0, 0x0000         /* clear bit 0 */
1068         mtdccr  r3
1069         blr
1070
1071         .globl  dcache_status
1072 dcache_status:
1073         mfdccr  r3
1074         srwi    r3, r3, 31      /* >>31 => select bit 0 */
1075         blr
1076
1077         .globl get_pvr
1078 get_pvr:
1079         mfspr   r3, PVR
1080         blr
1081
1082 #if !defined(CONFIG_440)
1083         .globl wr_pit
1084 wr_pit:
1085         mtspr   pit, r3
1086         blr
1087 #endif
1088
1089         .globl wr_tcr
1090 wr_tcr:
1091         mtspr   tcr, r3
1092         blr
1093
1094 /*------------------------------------------------------------------------------- */
1095 /* Function:     in8 */
1096 /* Description:  Input 8 bits */
1097 /*------------------------------------------------------------------------------- */
1098         .globl  in8
1099 in8:
1100         lbz     r3,0x0000(r3)
1101         blr
1102
1103 /*------------------------------------------------------------------------------- */
1104 /* Function:     out8 */
1105 /* Description:  Output 8 bits */
1106 /*------------------------------------------------------------------------------- */
1107         .globl  out8
1108 out8:
1109         stb     r4,0x0000(r3)
1110         blr
1111
1112 /*------------------------------------------------------------------------------- */
1113 /* Function:     out16 */
1114 /* Description:  Output 16 bits */
1115 /*------------------------------------------------------------------------------- */
1116         .globl  out16
1117 out16:
1118         sth     r4,0x0000(r3)
1119         blr
1120
1121 /*------------------------------------------------------------------------------- */
1122 /* Function:     out16r */
1123 /* Description:  Byte reverse and output 16 bits */
1124 /*------------------------------------------------------------------------------- */
1125         .globl  out16r
1126 out16r:
1127         sthbrx  r4,r0,r3
1128         blr
1129
1130 /*------------------------------------------------------------------------------- */
1131 /* Function:     out32 */
1132 /* Description:  Output 32 bits */
1133 /*------------------------------------------------------------------------------- */
1134         .globl  out32
1135 out32:
1136         stw     r4,0x0000(r3)
1137         blr
1138
1139 /*------------------------------------------------------------------------------- */
1140 /* Function:     out32r */
1141 /* Description:  Byte reverse and output 32 bits */
1142 /*------------------------------------------------------------------------------- */
1143         .globl  out32r
1144 out32r:
1145         stwbrx  r4,r0,r3
1146         blr
1147
1148 /*------------------------------------------------------------------------------- */
1149 /* Function:     in16 */
1150 /* Description:  Input 16 bits */
1151 /*------------------------------------------------------------------------------- */
1152         .globl  in16
1153 in16:
1154         lhz     r3,0x0000(r3)
1155         blr
1156
1157 /*------------------------------------------------------------------------------- */
1158 /* Function:     in16r */
1159 /* Description:  Input 16 bits and byte reverse */
1160 /*------------------------------------------------------------------------------- */
1161         .globl  in16r
1162 in16r:
1163         lhbrx   r3,r0,r3
1164         blr
1165
1166 /*------------------------------------------------------------------------------- */
1167 /* Function:     in32 */
1168 /* Description:  Input 32 bits */
1169 /*------------------------------------------------------------------------------- */
1170         .globl  in32
1171 in32:
1172         lwz     3,0x0000(3)
1173         blr
1174
1175 /*------------------------------------------------------------------------------- */
1176 /* Function:     in32r */
1177 /* Description:  Input 32 bits and byte reverse */
1178 /*------------------------------------------------------------------------------- */
1179         .globl  in32r
1180 in32r:
1181         lwbrx   r3,r0,r3
1182         blr
1183
1184 /*------------------------------------------------------------------------------- */
1185 /* Function:     ppcDcbf */
1186 /* Description:  Data Cache block flush */
1187 /* Input:        r3 = effective address */
1188 /* Output:       none. */
1189 /*------------------------------------------------------------------------------- */
1190         .globl  ppcDcbf
1191 ppcDcbf:
1192         dcbf    r0,r3
1193         blr
1194
1195 /*------------------------------------------------------------------------------- */
1196 /* Function:     ppcDcbi */
1197 /* Description:  Data Cache block Invalidate */
1198 /* Input:        r3 = effective address */
1199 /* Output:       none. */
1200 /*------------------------------------------------------------------------------- */
1201         .globl  ppcDcbi
1202 ppcDcbi:
1203         dcbi    r0,r3
1204         blr
1205
1206 /*------------------------------------------------------------------------------- */
1207 /* Function:     ppcSync */
1208 /* Description:  Processor Synchronize */
1209 /* Input:        none. */
1210 /* Output:       none. */
1211 /*------------------------------------------------------------------------------- */
1212         .globl  ppcSync
1213 ppcSync:
1214         sync
1215         blr
1216
1217 /*------------------------------------------------------------------------------*/
1218
1219 /*
1220  * void relocate_code (addr_sp, gd, addr_moni)
1221  *
1222  * This "function" does not return, instead it continues in RAM
1223  * after relocating the monitor code.
1224  *
1225  * r3 = dest
1226  * r4 = src
1227  * r5 = length in bytes
1228  * r6 = cachelinesize
1229  */
1230         .globl  relocate_code
1231 relocate_code:
1232         mr      r1,  r3         /* Set new stack pointer                */
1233         mr      r9,  r4         /* Save copy of Init Data pointer       */
1234         mr      r10, r5         /* Save copy of Destination Address     */
1235
1236         mr      r3,  r5                         /* Destination Address  */
1237         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
1238         ori     r4, r4, CFG_MONITOR_BASE@l
1239         lwz     r5, GOT(__init_end)
1240         sub     r5, r5, r4
1241         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
1242
1243         /*
1244          * Fix GOT pointer:
1245          *
1246          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
1247          *
1248          * Offset:
1249          */
1250         sub     r15, r10, r4
1251
1252         /* First our own GOT */
1253         add     r14, r14, r15
1254         /* the the one used by the C code */
1255         add     r30, r30, r15
1256
1257         /*
1258          * Now relocate code
1259          */
1260
1261         cmplw   cr1,r3,r4
1262         addi    r0,r5,3
1263         srwi.   r0,r0,2
1264         beq     cr1,4f          /* In place copy is not necessary       */
1265         beq     7f              /* Protect against 0 count              */
1266         mtctr   r0
1267         bge     cr1,2f
1268
1269         la      r8,-4(r4)
1270         la      r7,-4(r3)
1271 1:      lwzu    r0,4(r8)
1272         stwu    r0,4(r7)
1273         bdnz    1b
1274         b       4f
1275
1276 2:      slwi    r0,r0,2
1277         add     r8,r4,r0
1278         add     r7,r3,r0
1279 3:      lwzu    r0,-4(r8)
1280         stwu    r0,-4(r7)
1281         bdnz    3b
1282
1283 /*
1284  * Now flush the cache: note that we must start from a cache aligned
1285  * address. Otherwise we might miss one cache line.
1286  */
1287 4:      cmpwi   r6,0
1288         add     r5,r3,r5
1289         beq     7f              /* Always flush prefetch queue in any case */
1290         subi    r0,r6,1
1291         andc    r3,r3,r0
1292         mr      r4,r3
1293 5:      dcbst   0,r4
1294         add     r4,r4,r6
1295         cmplw   r4,r5
1296         blt     5b
1297         sync                    /* Wait for all dcbst to complete on bus */
1298         mr      r4,r3
1299 6:      icbi    0,r4
1300         add     r4,r4,r6
1301         cmplw   r4,r5
1302         blt     6b
1303 7:      sync                    /* Wait for all icbi to complete on bus */
1304         isync
1305
1306 /*
1307  * We are done. Do not return, instead branch to second part of board
1308  * initialization, now running from RAM.
1309  */
1310
1311         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1312         mtlr    r0
1313         blr                             /* NEVER RETURNS! */
1314
1315 in_ram:
1316
1317         /*
1318          * Relocation Function, r14 point to got2+0x8000
1319          *
1320          * Adjust got2 pointers, no need to check for 0, this code
1321          * already puts a few entries in the table.
1322          */
1323         li      r0,__got2_entries@sectoff@l
1324         la      r3,GOT(_GOT2_TABLE_)
1325         lwz     r11,GOT(_GOT2_TABLE_)
1326         mtctr   r0
1327         sub     r11,r3,r11
1328         addi    r3,r3,-4
1329 1:      lwzu    r0,4(r3)
1330         add     r0,r0,r11
1331         stw     r0,0(r3)
1332         bdnz    1b
1333
1334         /*
1335          * Now adjust the fixups and the pointers to the fixups
1336          * in case we need to move ourselves again.
1337          */
1338 2:      li      r0,__fixup_entries@sectoff@l
1339         lwz     r3,GOT(_FIXUP_TABLE_)
1340         cmpwi   r0,0
1341         mtctr   r0
1342         addi    r3,r3,-4
1343         beq     4f
1344 3:      lwzu    r4,4(r3)
1345         lwzux   r0,r4,r11
1346         add     r0,r0,r11
1347         stw     r10,0(r3)
1348         stw     r0,0(r4)
1349         bdnz    3b
1350 4:
1351 clear_bss:
1352         /*
1353          * Now clear BSS segment
1354          */
1355         lwz     r3,GOT(__bss_start)
1356         lwz     r4,GOT(_end)
1357
1358         cmplw   0, r3, r4
1359         beq     6f
1360
1361         li      r0, 0
1362 5:
1363         stw     r0, 0(r3)
1364         addi    r3, r3, 4
1365         cmplw   0, r3, r4
1366         bne     5b
1367 6:
1368
1369         mr      r3, r9          /* Init Data pointer            */
1370         mr      r4, r10         /* Destination Address          */
1371         bl      board_init_r
1372
1373         /*
1374          * Copy exception vector code to low memory
1375          *
1376          * r3: dest_addr
1377          * r7: source address, r8: end address, r9: target address
1378          */
1379         .globl  trap_init
1380 trap_init:
1381         lwz     r7, GOT(_start)
1382         lwz     r8, GOT(_end_of_vectors)
1383
1384         rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
1385
1386         cmplw   0, r7, r8
1387         bgelr                           /* return if r7>=r8 - just in case */
1388
1389         mflr    r4                      /* save link register           */
1390 1:
1391         lwz     r0, 0(r7)
1392         stw     r0, 0(r9)
1393         addi    r7, r7, 4
1394         addi    r9, r9, 4
1395         cmplw   0, r7, r8
1396         bne     1b
1397
1398         /*
1399          * relocate `hdlr' and `int_return' entries
1400          */
1401         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1402         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1403 2:
1404         bl      trap_reloc
1405         addi    r7, r7, 0x100           /* next exception vector        */
1406         cmplw   0, r7, r8
1407         blt     2b
1408
1409         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1410         bl      trap_reloc
1411
1412         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1413         bl      trap_reloc
1414
1415         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1416         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1417 3:
1418         bl      trap_reloc
1419         addi    r7, r7, 0x100           /* next exception vector        */
1420         cmplw   0, r7, r8
1421         blt     3b
1422
1423         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1424         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1425 4:
1426         bl      trap_reloc
1427         addi    r7, r7, 0x100           /* next exception vector        */
1428         cmplw   0, r7, r8
1429         blt     4b
1430
1431         mtlr    r4                      /* restore link register        */
1432         blr
1433
1434         /*
1435          * Function: relocate entries for one exception vector
1436          */
1437 trap_reloc:
1438         lwz     r0, 0(r7)               /* hdlr ...                     */
1439         add     r0, r0, r3              /*  ... += dest_addr            */
1440         stw     r0, 0(r7)
1441
1442         lwz     r0, 4(r7)               /* int_return ...               */
1443         add     r0, r0, r3              /*  ... += dest_addr            */
1444         stw     r0, 4(r7)
1445
1446         blr
1447
1448
1449 /**************************************************************************/
1450 /* PPC405EP specific stuff                                                */
1451 /**************************************************************************/
1452 #ifdef CONFIG_405EP
1453 ppc405ep_init:
1454         /*
1455         !-----------------------------------------------------------------------
1456         ! Check FPGA for PCI internal/external arbitration
1457         !   If board is set to internal arbitration, update cpc0_pci
1458         !-----------------------------------------------------------------------
1459         */
1460         addi    r3,0,CPC0_PCI_HOST_CFG_EN
1461 #ifdef CONFIG_BUBINGA405EP
1462         addis   r5,r0,FPGA_REG1@h      /* set offset for FPGA_REG1 */
1463         ori     r5,r5,FPGA_REG1@l
1464         lbz     r5,0x0(r5)              /* read to get PCI arb selection */
1465         andi.   r6,r5,FPGA_REG1_PCI_INT_ARB  /* using internal arbiter ?*/
1466         beq     ..pci_cfg_set             /* if not set, then bypass reg write*/
1467 #endif
1468         ori     r3,r3,CPC0_PCI_ARBIT_EN
1469 ..pci_cfg_set:
1470         mtdcr   CPC0_PCI, r3             /* Enable internal arbiter*/
1471
1472         /*
1473         !-----------------------------------------------------------------------
1474         ! Check to see if chip is in bypass mode.
1475         ! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a
1476         ! CPU reset   Otherwise, skip this step and keep going.
1477         ! Note:  Running BIOS in bypass mode is not supported since PLB speed
1478         !        will not be fast enough for the SDRAM (min 66MHz)
1479         !-----------------------------------------------------------------------
1480         */
1481         mfdcr   r5, CPC0_PLLMR1
1482         rlwinm  r4,r5,1,0x1            /* get system clock source (SSCS) */
1483         cmpi    cr0,0,r4,0x1
1484
1485         beq    pll_done                   /* if SSCS =b'1' then PLL has */
1486                                           /* already been set */
1487                                           /* and CPU has been reset */
1488                                           /* so skip to next section */
1489
1490 #ifdef CONFIG_BUBINGA405EP
1491         /*
1492         !-----------------------------------------------------------------------
1493         ! Read NVRAM to get value to write in PLLMR.
1494         ! If value has not been correctly saved, write default value
1495         ! Default config values (assuming on-board 33MHz SYS_CLK) are above.
1496         ! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above.
1497         !
1498         ! WARNING:  This code assumes the first three words in the nvram_t
1499         !           structure in openbios.h.  Changing the beginning of
1500         !           the structure will break this code.
1501         !
1502         !-----------------------------------------------------------------------
1503         */
1504         addis   r3,0,NVRAM_BASE@h
1505         addi    r3,r3,NVRAM_BASE@l
1506
1507         lwz     r4, 0(r3)
1508         addis   r5,0,NVRVFY1@h
1509         addi    r5,r5,NVRVFY1@l
1510         cmp     cr0,0,r4,r5            /* Compare 1st NVRAM Magic number*/
1511         bne     ..no_pllset
1512         addi    r3,r3,4
1513         lwz     r4, 0(r3)
1514         addis   r5,0,NVRVFY2@h
1515         addi    r5,r5,NVRVFY2@l
1516         cmp     cr0,0,r4,r5            /* Compare 2 NVRAM Magic number */
1517         bne     ..no_pllset
1518         addi    r3,r3,8                 /* Skip over conf_size */
1519         lwz     r4, 4(r3)               /* Load PLLMR1 value from NVRAM */
1520         lwz     r3, 0(r3)               /* Load PLLMR0 value from NVRAM */
1521         rlwinm  r5,r4,1,0x1             /* get system clock source (SSCS) */
1522         cmpi     cr0,0,r5,1             /* See if PLL is locked */
1523         beq     pll_write
1524 ..no_pllset:
1525 #endif /* CONFIG_BUBINGA405EP */
1526
1527         addis   r3,0,PLLMR0_DEFAULT@h       /* PLLMR0 default value */
1528         ori     r3,r3,PLLMR0_DEFAULT@l     /* */
1529         addis   r4,0,PLLMR1_DEFAULT@h       /* PLLMR1 default value */
1530         ori     r4,r4,PLLMR1_DEFAULT@l     /* */
1531
1532         b       pll_write                 /* Write the CPC0_PLLMR with new value */
1533
1534 pll_done:
1535         /*
1536         !-----------------------------------------------------------------------
1537         ! Clear Soft Reset Register
1538         ! This is needed to enable PCI if not booting from serial EPROM
1539         !-----------------------------------------------------------------------
1540                 */
1541         addi    r3, 0, 0x0
1542         mtdcr   CPC0_SRR, r3
1543
1544         addis    r3,0,0x0010
1545         mtctr   r3
1546 pci_wait:
1547         bdnz    pci_wait
1548
1549         blr                               /* return to main code */
1550
1551 /*
1552 !-----------------------------------------------------------------------------
1553 ! Function:     pll_write
1554 ! Description:  Updates the value of the CPC0_PLLMR according to CMOS27E documentation
1555 !               That is:
1556 !                         1.  Pll is first disabled (de-activated by putting in bypass mode)
1557 !                         2.  PLL is reset
1558 !                         3.  Clock dividers are set while PLL is held in reset and bypassed
1559 !                         4.  PLL Reset is cleared
1560 !                         5.  Wait 100us for PLL to lock
1561 !                         6.  A core reset is performed
1562 ! Input: r3 = Value to write to CPC0_PLLMR0
1563 ! Input: r4 = Value to write to CPC0_PLLMR1
1564 ! Output r3 = none
1565 !-----------------------------------------------------------------------------
1566 */
1567 pll_write:
1568         mfdcr  r5, CPC0_UCR
1569         andis. r5,r5,0xFFFF
1570         ori    r5,r5,0x0101              /* Stop the UART clocks */
1571         mtdcr  CPC0_UCR,r5               /* Before changing PLL */
1572
1573         mfdcr  r5, CPC0_PLLMR1
1574         rlwinm r5,r5,0,0x7FFFFFFF        /* Disable PLL */
1575         mtdcr   CPC0_PLLMR1,r5
1576         oris   r5,r5,0x4000              /* Set PLL Reset */
1577         mtdcr   CPC0_PLLMR1,r5
1578
1579         mtdcr   CPC0_PLLMR0,r3           /* Set clock dividers */
1580         rlwinm r5,r4,0,0x3FFFFFFF        /* Reset & Bypass new PLL dividers */
1581         oris   r5,r5,0x4000              /* Set PLL Reset */
1582         mtdcr   CPC0_PLLMR1,r5           /* Set clock dividers */
1583         rlwinm r5,r5,0,0xBFFFFFFF        /* Clear PLL Reset */
1584         mtdcr   CPC0_PLLMR1,r5
1585
1586                 /*
1587         ! Wait min of 100us for PLL to lock.
1588         ! See CMOS 27E databook for more info.
1589         ! At 200MHz, that means waiting 20,000 instructions
1590                  */
1591         addi    r3,0,20000              /* 2000 = 0x4e20 */
1592         mtctr   r3
1593 pll_wait:
1594         bdnz    pll_wait
1595
1596         oris   r5,r5,0x8000             /* Enable PLL */
1597         mtdcr   CPC0_PLLMR1,r5          /* Engage */
1598
1599         /*
1600          * Reset CPU to guarantee timings are OK
1601          * Not sure if this is needed...
1602          */
1603         addis r3,0,0x1000
1604         mtspr dbcr0,r3               /* This will cause a CPU core reset, and */
1605                                      /* execution will continue from the poweron */
1606                                      /* vector of 0xfffffffc */
1607 #endif /* CONFIG_405EP */