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