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