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