* Implement new mechanism to export U-Boot's functions to standalone
[kernel/u-boot.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         CRIT_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         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
773         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
774
775         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
776         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
777
778         /* On the MPC8xx, this is a software emulation interrupt.  It occurs
779          * for all unimplemented and illegal instructions.
780          */
781         STD_EXCEPTION(0x1000, PIT, PITException)
782
783         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
784         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
785         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
786         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
787
788         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
789         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
790         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
791         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
792         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
793         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
794         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
795
796         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
797         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
798         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
799         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
800
801         CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
802
803         .globl  _end_of_vectors
804 _end_of_vectors:
805
806
807         . = 0x2100
808
809 /*
810  * This code finishes saving the registers to the exception frame
811  * and jumps to the appropriate handler for the exception.
812  * Register r21 is pointer into trap frame, r1 has new stack pointer.
813  */
814         .globl  transfer_to_handler
815 transfer_to_handler:
816         stw     r22,_NIP(r21)
817         lis     r22,MSR_POW@h
818         andc    r23,r23,r22
819         stw     r23,_MSR(r21)
820         SAVE_GPR(7, r21)
821         SAVE_4GPRS(8, r21)
822         SAVE_8GPRS(12, r21)
823         SAVE_8GPRS(24, r21)
824 #if 0
825         andi.   r23,r23,MSR_PR
826         mfspr   r23,SPRG3               /* if from user, fix up tss.regs */
827         beq     2f
828         addi    r24,r1,STACK_FRAME_OVERHEAD
829         stw     r24,PT_REGS(r23)
830 2:      addi    r2,r23,-TSS             /* set r2 to current */
831         tovirt(r2,r2,r23)
832 #endif
833         mflr    r23
834         andi.   r24,r23,0x3f00          /* get vector offset */
835         stw     r24,TRAP(r21)
836         li      r22,0
837         stw     r22,RESULT(r21)
838         mtspr   SPRG2,r22               /* r1 is now kernel sp */
839 #if 0
840         addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
841         cmplw   0,r1,r2
842         cmplw   1,r1,r24
843         crand   1,1,4
844         bgt     stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
845 #endif
846         lwz     r24,0(r23)              /* virtual address of handler */
847         lwz     r23,4(r23)              /* where to go when done */
848         mtspr   SRR0,r24
849         mtspr   SRR1,r20
850         mtlr    r23
851         SYNC
852         rfi                             /* jump to handler, enable MMU */
853
854 int_return:
855         mfmsr   r28             /* Disable interrupts */
856         li      r4,0
857         ori     r4,r4,MSR_EE
858         andc    r28,r28,r4
859         SYNC                    /* Some chip revs need this... */
860         mtmsr   r28
861         SYNC
862         lwz     r2,_CTR(r1)
863         lwz     r0,_LINK(r1)
864         mtctr   r2
865         mtlr    r0
866         lwz     r2,_XER(r1)
867         lwz     r0,_CCR(r1)
868         mtspr   XER,r2
869         mtcrf   0xFF,r0
870         REST_10GPRS(3, r1)
871         REST_10GPRS(13, r1)
872         REST_8GPRS(23, r1)
873         REST_GPR(31, r1)
874         lwz     r2,_NIP(r1)     /* Restore environment */
875         lwz     r0,_MSR(r1)
876         mtspr   SRR0,r2
877         mtspr   SRR1,r0
878         lwz     r0,GPR0(r1)
879         lwz     r2,GPR2(r1)
880         lwz     r1,GPR1(r1)
881         SYNC
882         rfi
883
884 crit_return:
885         mfmsr   r28             /* Disable interrupts */
886         li      r4,0
887         ori     r4,r4,MSR_EE
888         andc    r28,r28,r4
889         SYNC                    /* Some chip revs need this... */
890         mtmsr   r28
891         SYNC
892         lwz     r2,_CTR(r1)
893         lwz     r0,_LINK(r1)
894         mtctr   r2
895         mtlr    r0
896         lwz     r2,_XER(r1)
897         lwz     r0,_CCR(r1)
898         mtspr   XER,r2
899         mtcrf   0xFF,r0
900         REST_10GPRS(3, r1)
901         REST_10GPRS(13, r1)
902         REST_8GPRS(23, r1)
903         REST_GPR(31, r1)
904         lwz     r2,_NIP(r1)     /* Restore environment */
905         lwz     r0,_MSR(r1)
906         mtspr   990,r2          /* SRR2 */
907         mtspr   991,r0          /* SRR3 */
908         lwz     r0,GPR0(r1)
909         lwz     r2,GPR2(r1)
910         lwz     r1,GPR1(r1)
911         SYNC
912         rfci
913
914 /* Cache functions.
915 */
916 invalidate_icache:
917         iccci   r0,r0                   /* for 405, iccci invalidates the */
918         blr                             /*   entire I cache */
919
920 invalidate_dcache:
921         addi    r6,0,0x0000             /* clear GPR 6 */
922         /* Do loop for # of dcache congruence classes. */
923         addi    r7,r0, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
924                                         /* NOTE: dccci invalidates both */
925         mtctr   r7                      /* ways in the D cache */
926 ..dcloop:
927         dccci   0,r6                    /* invalidate line */
928         addi    r6,r6, CFG_CACHELINE_SIZE /* bump to next line */
929         bdnz    ..dcloop
930         blr
931
932 flush_dcache:
933         addis   r9,r0,0x0002            /* set mask for EE and CE msr bits */
934         ori     r9,r9,0x8000
935         mfmsr   r12                     /* save msr */
936         andc    r9,r12,r9
937         mtmsr   r9                      /* disable EE and CE */
938         addi    r10,r0,0x0001           /* enable data cache for unused memory */
939         mfdccr  r9                      /* region 0xF8000000-0xFFFFFFFF via */
940         or      r10,r10,r9              /* bit 31 in dccr */
941         mtdccr  r10
942
943         /* do loop for # of congruence classes. */
944         addi    r10,r0,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
945         addi    r11,r0,(CFG_DCACHE_SIZE / 2) /* D cache set size - 2 way sets */
946         mtctr   r10
947         addi    r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */
948         add     r11,r10,r11             /* add to get to other side of cache line */
949 ..flush_dcache_loop:
950         lwz     r3,0(r10)               /* least recently used side */
951         lwz     r3,0(r11)               /* the other side */
952         dccci   r0,r11                  /* invalidate both sides */
953         addi    r10,r10,CFG_CACHELINE_SIZE /* bump to next line */
954         addi    r11,r11,CFG_CACHELINE_SIZE /* bump to next line */
955         bdnz    ..flush_dcache_loop
956         sync                            /* allow memory access to complete */
957         mtdccr  r9                      /* restore dccr */
958         mtmsr   r12                     /* restore msr */
959         blr
960
961         .globl  icache_enable
962 icache_enable:
963         mflr    r8
964         bl      invalidate_icache
965         mtlr    r8
966         isync
967         addis   r3,r0, 0x8000         /* set bit 0 */
968         mticcr  r3
969         blr
970
971         .globl  icache_disable
972 icache_disable:
973         addis   r3,r0, 0x0000         /* clear bit 0 */
974         mticcr  r3
975         isync
976         blr
977
978         .globl  icache_status
979 icache_status:
980         mficcr  r3
981         srwi    r3, r3, 31      /* >>31 => select bit 0 */
982         blr
983
984         .globl  dcache_enable
985 dcache_enable:
986         mflr    r8
987         bl      invalidate_dcache
988         mtlr    r8
989         isync
990         addis   r3,r0, 0x8000         /* set bit 0 */
991         mtdccr  r3
992         blr
993
994         .globl  dcache_disable
995 dcache_disable:
996         mflr    r8
997         bl      flush_dcache
998         mtlr    r8
999         addis   r3,r0, 0x0000         /* clear bit 0 */
1000         mtdccr  r3
1001         blr
1002
1003         .globl  dcache_status
1004 dcache_status:
1005         mfdccr  r3
1006         srwi    r3, r3, 31      /* >>31 => select bit 0 */
1007         blr
1008
1009         .globl get_pvr
1010 get_pvr:
1011         mfspr   r3, PVR
1012         blr
1013
1014 #if !defined(CONFIG_440)
1015         .globl wr_pit
1016 wr_pit:
1017         mtspr   pit, r3
1018         blr
1019 #endif
1020
1021         .globl wr_tcr
1022 wr_tcr:
1023         mtspr   tcr, r3
1024         blr
1025
1026 /*------------------------------------------------------------------------------- */
1027 /* Function:     in8 */
1028 /* Description:  Input 8 bits */
1029 /*------------------------------------------------------------------------------- */
1030         .globl  in8
1031 in8:
1032         lbz     r3,0x0000(r3)
1033         blr
1034
1035 /*------------------------------------------------------------------------------- */
1036 /* Function:     out8 */
1037 /* Description:  Output 8 bits */
1038 /*------------------------------------------------------------------------------- */
1039         .globl  out8
1040 out8:
1041         stb     r4,0x0000(r3)
1042         blr
1043
1044 /*------------------------------------------------------------------------------- */
1045 /* Function:     out16 */
1046 /* Description:  Output 16 bits */
1047 /*------------------------------------------------------------------------------- */
1048         .globl  out16
1049 out16:
1050         sth     r4,0x0000(r3)
1051         blr
1052
1053 /*------------------------------------------------------------------------------- */
1054 /* Function:     out16r */
1055 /* Description:  Byte reverse and output 16 bits */
1056 /*------------------------------------------------------------------------------- */
1057         .globl  out16r
1058 out16r:
1059         sthbrx  r4,r0,r3
1060         blr
1061
1062 /*------------------------------------------------------------------------------- */
1063 /* Function:     out32 */
1064 /* Description:  Output 32 bits */
1065 /*------------------------------------------------------------------------------- */
1066         .globl  out32
1067 out32:
1068         stw     r4,0x0000(r3)
1069         blr
1070
1071 /*------------------------------------------------------------------------------- */
1072 /* Function:     out32r */
1073 /* Description:  Byte reverse and output 32 bits */
1074 /*------------------------------------------------------------------------------- */
1075         .globl  out32r
1076 out32r:
1077         stwbrx  r4,r0,r3
1078         blr
1079
1080 /*------------------------------------------------------------------------------- */
1081 /* Function:     in16 */
1082 /* Description:  Input 16 bits */
1083 /*------------------------------------------------------------------------------- */
1084         .globl  in16
1085 in16:
1086         lhz     r3,0x0000(r3)
1087         blr
1088
1089 /*------------------------------------------------------------------------------- */
1090 /* Function:     in16r */
1091 /* Description:  Input 16 bits and byte reverse */
1092 /*------------------------------------------------------------------------------- */
1093         .globl  in16r
1094 in16r:
1095         lhbrx   r3,r0,r3
1096         blr
1097
1098 /*------------------------------------------------------------------------------- */
1099 /* Function:     in32 */
1100 /* Description:  Input 32 bits */
1101 /*------------------------------------------------------------------------------- */
1102         .globl  in32
1103 in32:
1104         lwz     3,0x0000(3)
1105         blr
1106
1107 /*------------------------------------------------------------------------------- */
1108 /* Function:     in32r */
1109 /* Description:  Input 32 bits and byte reverse */
1110 /*------------------------------------------------------------------------------- */
1111         .globl  in32r
1112 in32r:
1113         lwbrx   r3,r0,r3
1114         blr
1115
1116 /*------------------------------------------------------------------------------- */
1117 /* Function:     ppcDcbf */
1118 /* Description:  Data Cache block flush */
1119 /* Input:        r3 = effective address */
1120 /* Output:       none. */
1121 /*------------------------------------------------------------------------------- */
1122         .globl  ppcDcbf
1123 ppcDcbf:
1124         dcbf    r0,r3
1125         blr
1126
1127 /*------------------------------------------------------------------------------- */
1128 /* Function:     ppcDcbi */
1129 /* Description:  Data Cache block Invalidate */
1130 /* Input:        r3 = effective address */
1131 /* Output:       none. */
1132 /*------------------------------------------------------------------------------- */
1133         .globl  ppcDcbi
1134 ppcDcbi:
1135         dcbi    r0,r3
1136         blr
1137
1138 /*------------------------------------------------------------------------------- */
1139 /* Function:     ppcSync */
1140 /* Description:  Processor Synchronize */
1141 /* Input:        none. */
1142 /* Output:       none. */
1143 /*------------------------------------------------------------------------------- */
1144         .globl  ppcSync
1145 ppcSync:
1146         sync
1147         blr
1148
1149 /*------------------------------------------------------------------------------*/
1150
1151 /*
1152  * void relocate_code (addr_sp, gd, addr_moni)
1153  *
1154  * This "function" does not return, instead it continues in RAM
1155  * after relocating the monitor code.
1156  *
1157  * r3 = dest
1158  * r4 = src
1159  * r5 = length in bytes
1160  * r6 = cachelinesize
1161  */
1162         .globl  relocate_code
1163 relocate_code:
1164         mr      r1,  r3         /* Set new stack pointer                */
1165         mr      r9,  r4         /* Save copy of Init Data pointer       */
1166         mr      r10, r5         /* Save copy of Destination Address     */
1167
1168         mr      r3,  r5                         /* Destination Address  */
1169         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
1170         ori     r4, r4, CFG_MONITOR_BASE@l
1171         lwz     r5, GOT(__init_end)
1172         sub     r5, r5, r4
1173         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
1174
1175         /*
1176          * Fix GOT pointer:
1177          *
1178          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
1179          *
1180          * Offset:
1181          */
1182         sub     r15, r10, r4
1183
1184         /* First our own GOT */
1185         add     r14, r14, r15
1186         /* the the one used by the C code */
1187         add     r30, r30, r15
1188
1189         /*
1190          * Now relocate code
1191          */
1192
1193         cmplw   cr1,r3,r4
1194         addi    r0,r5,3
1195         srwi.   r0,r0,2
1196         beq     cr1,4f          /* In place copy is not necessary       */
1197         beq     7f              /* Protect against 0 count              */
1198         mtctr   r0
1199         bge     cr1,2f
1200
1201         la      r8,-4(r4)
1202         la      r7,-4(r3)
1203 1:      lwzu    r0,4(r8)
1204         stwu    r0,4(r7)
1205         bdnz    1b
1206         b       4f
1207
1208 2:      slwi    r0,r0,2
1209         add     r8,r4,r0
1210         add     r7,r3,r0
1211 3:      lwzu    r0,-4(r8)
1212         stwu    r0,-4(r7)
1213         bdnz    3b
1214
1215 /*
1216  * Now flush the cache: note that we must start from a cache aligned
1217  * address. Otherwise we might miss one cache line.
1218  */
1219 4:      cmpwi   r6,0
1220         add     r5,r3,r5
1221         beq     7f              /* Always flush prefetch queue in any case */
1222         subi    r0,r6,1
1223         andc    r3,r3,r0
1224         mr      r4,r3
1225 5:      dcbst   0,r4
1226         add     r4,r4,r6
1227         cmplw   r4,r5
1228         blt     5b
1229         sync                    /* Wait for all dcbst to complete on bus */
1230         mr      r4,r3
1231 6:      icbi    0,r4
1232         add     r4,r4,r6
1233         cmplw   r4,r5
1234         blt     6b
1235 7:      sync                    /* Wait for all icbi to complete on bus */
1236         isync
1237
1238 /*
1239  * We are done. Do not return, instead branch to second part of board
1240  * initialization, now running from RAM.
1241  */
1242
1243         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1244         mtlr    r0
1245         blr                             /* NEVER RETURNS! */
1246
1247 in_ram:
1248
1249         /*
1250          * Relocation Function, r14 point to got2+0x8000
1251          *
1252          * Adjust got2 pointers, no need to check for 0, this code
1253          * already puts a few entries in the table.
1254          */
1255         li      r0,__got2_entries@sectoff@l
1256         la      r3,GOT(_GOT2_TABLE_)
1257         lwz     r11,GOT(_GOT2_TABLE_)
1258         mtctr   r0
1259         sub     r11,r3,r11
1260         addi    r3,r3,-4
1261 1:      lwzu    r0,4(r3)
1262         add     r0,r0,r11
1263         stw     r0,0(r3)
1264         bdnz    1b
1265
1266         /*
1267          * Now adjust the fixups and the pointers to the fixups
1268          * in case we need to move ourselves again.
1269          */
1270 2:      li      r0,__fixup_entries@sectoff@l
1271         lwz     r3,GOT(_FIXUP_TABLE_)
1272         cmpwi   r0,0
1273         mtctr   r0
1274         addi    r3,r3,-4
1275         beq     4f
1276 3:      lwzu    r4,4(r3)
1277         lwzux   r0,r4,r11
1278         add     r0,r0,r11
1279         stw     r10,0(r3)
1280         stw     r0,0(r4)
1281         bdnz    3b
1282 4:
1283 clear_bss:
1284         /*
1285          * Now clear BSS segment
1286          */
1287         lwz     r3,GOT(__bss_start)
1288         lwz     r4,GOT(_end)
1289
1290         cmplw   0, r3, r4
1291         beq     6f
1292
1293         li      r0, 0
1294 5:
1295         stw     r0, 0(r3)
1296         addi    r3, r3, 4
1297         cmplw   0, r3, r4
1298         bne     5b
1299 6:
1300
1301         mr      r3, r9          /* Init Data pointer            */
1302         mr      r4, r10         /* Destination Address          */
1303         bl      board_init_r
1304
1305         /*
1306          * Copy exception vector code to low memory
1307          *
1308          * r3: dest_addr
1309          * r7: source address, r8: end address, r9: target address
1310          */
1311         .globl  trap_init
1312 trap_init:
1313         lwz     r7, GOT(_start)
1314         lwz     r8, GOT(_end_of_vectors)
1315
1316         li      r9, 0x100               /* reset vector always at 0x100 */
1317
1318         cmplw   0, r7, r8
1319         bgelr                           /* return if r7>=r8 - just in case */
1320
1321         mflr    r4                      /* save link register           */
1322 1:
1323         lwz     r0, 0(r7)
1324         stw     r0, 0(r9)
1325         addi    r7, r7, 4
1326         addi    r9, r9, 4
1327         cmplw   0, r7, r8
1328         bne     1b
1329
1330         /*
1331          * relocate `hdlr' and `int_return' entries
1332          */
1333         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1334         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1335 2:
1336         bl      trap_reloc
1337         addi    r7, r7, 0x100           /* next exception vector        */
1338         cmplw   0, r7, r8
1339         blt     2b
1340
1341         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1342         bl      trap_reloc
1343
1344         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1345         bl      trap_reloc
1346
1347         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1348         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1349 3:
1350         bl      trap_reloc
1351         addi    r7, r7, 0x100           /* next exception vector        */
1352         cmplw   0, r7, r8
1353         blt     3b
1354
1355         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1356         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1357 4:
1358         bl      trap_reloc
1359         addi    r7, r7, 0x100           /* next exception vector        */
1360         cmplw   0, r7, r8
1361         blt     4b
1362
1363         mtlr    r4                      /* restore link register        */
1364         blr
1365
1366         /*
1367          * Function: relocate entries for one exception vector
1368          */
1369 trap_reloc:
1370         lwz     r0, 0(r7)               /* hdlr ...                     */
1371         add     r0, r0, r3              /*  ... += dest_addr            */
1372         stw     r0, 0(r7)
1373
1374         lwz     r0, 4(r7)               /* int_return ...               */
1375         add     r0, r0, r3              /*  ... += dest_addr            */
1376         stw     r0, 4(r7)
1377
1378         blr
1379
1380
1381 /**************************************************************************/
1382 /* PPC405EP specific stuff                                                */
1383 /**************************************************************************/
1384 #ifdef CONFIG_405EP
1385 ppc405ep_init:
1386         /*
1387         !-----------------------------------------------------------------------
1388         ! Check FPGA for PCI internal/external arbitration
1389         !   If board is set to internal arbitration, update cpc0_pci
1390         !-----------------------------------------------------------------------
1391         */
1392         addi    r3,0,CPC0_PCI_HOST_CFG_EN
1393 #ifdef CONFIG_BUBINGA405EP
1394         addis   r5,r0,FPGA_REG1@h      /* set offset for FPGA_REG1 */
1395         ori     r5,r5,FPGA_REG1@l
1396         lbz     r5,0x0(r5)              /* read to get PCI arb selection */
1397         andi.   r6,r5,FPGA_REG1_PCI_INT_ARB  /* using internal arbiter ?*/
1398         beq     ..pci_cfg_set             /* if not set, then bypass reg write*/
1399 #endif
1400         ori     r3,r3,CPC0_PCI_ARBIT_EN
1401 ..pci_cfg_set:
1402         mtdcr   CPC0_PCI, r3             /* Enable internal arbiter*/
1403
1404         /*
1405         !-----------------------------------------------------------------------
1406         ! Check to see if chip is in bypass mode.
1407         ! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a
1408         ! CPU reset   Otherwise, skip this step and keep going.
1409         ! Note:  Running BIOS in bypass mode is not supported since PLB speed
1410         !        will not be fast enough for the SDRAM (min 66MHz)
1411         !-----------------------------------------------------------------------
1412         */
1413         mfdcr   r5, CPC0_PLLMR1
1414         rlwinm  r4,r5,1,0x1            /* get system clock source (SSCS) */
1415         cmpi    cr0,0,r4,0x1
1416
1417         beq    pll_done                   /* if SSCS =b'1' then PLL has */
1418                                           /* already been set */
1419                                           /* and CPU has been reset */
1420                                           /* so skip to next section */
1421
1422 #ifdef CONFIG_BUBINGA405EP
1423         /*
1424         !-----------------------------------------------------------------------
1425         ! Read NVRAM to get value to write in PLLMR.
1426         ! If value has not been correctly saved, write default value
1427         ! Default config values (assuming on-board 33MHz SYS_CLK) are above.
1428         ! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above.
1429         !
1430         ! WARNING:  This code assumes the first three words in the nvram_t
1431         !           structure in openbios.h.  Changing the beginning of
1432         !           the structure will break this code.
1433         !
1434         !-----------------------------------------------------------------------
1435         */
1436         addis   r3,0,NVRAM_BASE@h
1437         addi    r3,r3,NVRAM_BASE@l
1438
1439         lwz     r4, 0(r3)
1440         addis   r5,0,NVRVFY1@h
1441         addi    r5,r5,NVRVFY1@l
1442         cmp     cr0,0,r4,r5            /* Compare 1st NVRAM Magic number*/
1443         bne     ..no_pllset
1444         addi    r3,r3,4
1445         lwz     r4, 0(r3)
1446         addis   r5,0,NVRVFY2@h
1447         addi    r5,r5,NVRVFY2@l
1448         cmp     cr0,0,r4,r5            /* Compare 2 NVRAM Magic number */
1449         bne     ..no_pllset
1450         addi    r3,r3,8                 /* Skip over conf_size */
1451         lwz     r4, 4(r3)               /* Load PLLMR1 value from NVRAM */
1452         lwz     r3, 0(r3)               /* Load PLLMR0 value from NVRAM */
1453         rlwinm  r5,r4,1,0x1             /* get system clock source (SSCS) */
1454         cmpi     cr0,0,r5,1             /* See if PLL is locked */
1455         beq     pll_write
1456 ..no_pllset:
1457 #endif /* CONFIG_BUBINGA405EP */
1458
1459         addis   r3,0,PLLMR0_DEFAULT@h       /* PLLMR0 default value */
1460         ori     r3,r3,PLLMR0_DEFAULT@l     /* */
1461         addis   r4,0,PLLMR1_DEFAULT@h       /* PLLMR1 default value */
1462         ori     r4,r4,PLLMR1_DEFAULT@l     /* */
1463
1464         b       pll_write                 /* Write the CPC0_PLLMR with new value */
1465
1466 pll_done:
1467         /*
1468         !-----------------------------------------------------------------------
1469         ! Clear Soft Reset Register
1470         ! This is needed to enable PCI if not booting from serial EPROM
1471         !-----------------------------------------------------------------------
1472                 */
1473         addi    r3, 0, 0x0
1474         mtdcr   CPC0_SRR, r3
1475
1476         addis    r3,0,0x0010
1477         mtctr   r3
1478 pci_wait:
1479         bdnz    pci_wait
1480
1481         blr                               /* return to main code */
1482
1483 /*
1484 !-----------------------------------------------------------------------------
1485 ! Function:     pll_write
1486 ! Description:  Updates the value of the CPC0_PLLMR according to CMOS27E documentation
1487 !               That is:
1488 !                         1.  Pll is first disabled (de-activated by putting in bypass mode)
1489 !                         2.  PLL is reset
1490 !                         3.  Clock dividers are set while PLL is held in reset and bypassed
1491 !                         4.  PLL Reset is cleared
1492 !                         5.  Wait 100us for PLL to lock
1493 !                         6.  A core reset is performed
1494 ! Input: r3 = Value to write to CPC0_PLLMR0
1495 ! Input: r4 = Value to write to CPC0_PLLMR1
1496 ! Output r3 = none
1497 !-----------------------------------------------------------------------------
1498 */
1499 pll_write:
1500         mfdcr  r5, CPC0_UCR
1501         andis. r5,r5,0xFFFF
1502         ori    r5,r5,0x0101              /* Stop the UART clocks */
1503         mtdcr  CPC0_UCR,r5               /* Before changing PLL */
1504
1505         mfdcr  r5, CPC0_PLLMR1
1506         rlwinm r5,r5,0,0x7FFFFFFF        /* Disable PLL */
1507         mtdcr   CPC0_PLLMR1,r5
1508         oris   r5,r5,0x4000              /* Set PLL Reset */
1509         mtdcr   CPC0_PLLMR1,r5
1510
1511         mtdcr   CPC0_PLLMR0,r3           /* Set clock dividers */
1512         rlwinm r5,r4,0,0x3FFFFFFF        /* Reset & Bypass new PLL dividers */
1513         oris   r5,r5,0x4000              /* Set PLL Reset */
1514         mtdcr   CPC0_PLLMR1,r5           /* Set clock dividers */
1515         rlwinm r5,r5,0,0xBFFFFFFF        /* Clear PLL Reset */
1516         mtdcr   CPC0_PLLMR1,r5
1517
1518                 /*
1519         ! Wait min of 100us for PLL to lock.
1520         ! See CMOS 27E databook for more info.
1521         ! At 200MHz, that means waiting 20,000 instructions
1522                  */
1523         addi    r3,0,20000              /* 2000 = 0x4e20 */
1524         mtctr   r3
1525 pll_wait:
1526         bdnz    pll_wait
1527
1528         oris   r5,r5,0x8000             /* Enable PLL */
1529         mtdcr   CPC0_PLLMR1,r5          /* Engage */
1530
1531         /*
1532          * Reset CPU to guarantee timings are OK
1533          * Not sure if this is needed...
1534          */
1535         addis r3,0,0x1000
1536         mtspr dbcr0,r3               /* This will cause a CPU core reset, and */
1537                                      /* execution will continue from the poweron */
1538                                      /* vector of 0xfffffffc */
1539 #endif /* CONFIG_405EP */