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