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