]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/start.S
* Patch by Hans-Joerg Frieden, 06 Dec 2002
[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 IBM 4xx PowerPC based Embedded Boards
46  *
47  *
48  *  The processor starts at 0xfffffffc and the code is executed
49  *  from flash/rom.
50  *  in memory, but as long we don't jump around before relocating.
51  *  board_init lies at a quite high address and when the cpu has
52  *  jumped there, everything is ok.
53  *  This works because the cpu gives the FLASH (CS0) the whole
54  *  address space at startup, and board_init lies as a echo of
55  *  the flash somewhere up there in the memorymap.
56  *
57  *  board_init will change CS0 to be positioned at the correct
58  *  address and (s)dram will be positioned at address 0
59  */
60 #include <config.h>
61 #include <mpc8xx.h>
62 #include <ppc4xx.h>
63 #include <version.h>
64
65 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
66
67 #include <ppc_asm.tmpl>
68 #include <ppc_defs.h>
69
70 #include <asm/cache.h>
71 #include <asm/mmu.h>
72
73 #ifndef  CONFIG_IDENT_STRING
74 #define  CONFIG_IDENT_STRING ""
75 #endif
76
77 #ifdef CFG_INIT_DCACHE_CS
78 # if (CFG_INIT_DCACHE_CS == 0)
79 #  define PBxAP pb0ap
80 #  define PBxCR pb0cr
81 # endif
82 # if (CFG_INIT_DCACHE_CS == 1)
83 #  define PBxAP pb1ap
84 #  define PBxCR pb1cr
85 # endif
86 # if (CFG_INIT_DCACHE_CS == 2)
87 #  define PBxAP pb2ap
88 #  define PBxCR pb2cr
89 # endif
90 # if (CFG_INIT_DCACHE_CS == 3)
91 #  define PBxAP pb3ap
92 #  define PBxCR pb3cr
93 # endif
94 # if (CFG_INIT_DCACHE_CS == 4)
95 #  define PBxAP pb4ap
96 #  define PBxCR pb4cr
97 # endif
98 # if (CFG_INIT_DCACHE_CS == 5)
99 #  define PBxAP pb5ap
100 #  define PBxCR pb5cr
101 # endif
102 # if (CFG_INIT_DCACHE_CS == 6)
103 #  define PBxAP pb6ap
104 #  define PBxCR pb6cr
105 # endif
106 # if (CFG_INIT_DCACHE_CS == 7)
107 #  define PBxAP pb7ap
108 #  define PBxCR pb7cr
109 # endif
110 #endif /* CFG_INIT_DCACHE_CS */
111
112 /* We don't want the  MMU yet.
113 */
114 #undef  MSR_KERNEL
115 #define MSR_KERNEL ( MSR_ME  )  /* Machine Check */
116
117
118         .extern ext_bus_cntlr_init
119         .extern sdram_init
120
121 /*
122  * Set up GOT: Global Offset Table
123  *
124  * Use r14 to access the GOT
125  */
126         START_GOT
127         GOT_ENTRY(_GOT2_TABLE_)
128         GOT_ENTRY(_FIXUP_TABLE_)
129
130         GOT_ENTRY(_start)
131         GOT_ENTRY(_start_of_vectors)
132         GOT_ENTRY(_end_of_vectors)
133         GOT_ENTRY(transfer_to_handler)
134
135         GOT_ENTRY(_end)
136         GOT_ENTRY(.bss)
137         END_GOT
138
139 /*
140  * 440 Startup -- on reset only the top 4k of the effective
141  * address space is mapped in by an entry in the instruction
142  * and data shadow TLB. The .bootpg section is located in the
143  * top 4k & does only what's necessary to map in the the rest
144  * of the boot rom. Once the boot rom is mapped in we can
145  * proceed with normal startup.
146  *
147  * NOTE: CS0 only covers the top 2MB of the effective address
148  * space after reset.
149  */
150
151 #if defined(CONFIG_440)
152     .section .bootpg,"ax"
153     .globl _start_440
154
155 /**************************************************************************/
156 _start_440:
157         /*----------------------------------------------------------------*/
158         /* Clear and set up some registers. */
159         /*----------------------------------------------------------------*/
160         iccci   r0,r0           /* NOTE: operands not used for 440 */
161         dccci   r0,r0           /* NOTE: operands not used for 440 */
162         sync
163         li      r0,0
164         mtspr   srr0,r0
165         mtspr   srr1,r0
166         mtspr   csrr0,r0
167         mtspr   csrr1,r0
168
169         /*----------------------------------------------------------------*/
170         /* Initialize debug */
171         /*----------------------------------------------------------------*/
172         mtspr   dbcr0,r0
173         mtspr   dbcr1,r0
174         mtspr   dbcr2,r0
175         mtspr   iac1,r0
176         mtspr   iac2,r0
177         mtspr   iac3,r0
178         mtspr   dac1,r0
179         mtspr   dac2,r0
180         mtspr   dvc1,r0
181         mtspr   dvc2,r0
182
183         mfspr   r1,dbsr
184         mtspr   dbsr,r1         /* Clear all valid bits */
185
186         /*----------------------------------------------------------------*/
187         /* CCR0 init */
188         /*----------------------------------------------------------------*/
189         /* Disable store gathering & broadcast, guarantee inst/data
190         * cache block touch, force load/store alignment
191         * (see errata 1.12: 440_33)
192         */
193         lis     r1,0x0030       /* store gathering & broadcast disable */
194         ori     r1,r1,0x6000    /* cache touch */
195         mtspr   ccr0,r1
196
197         /*----------------------------------------------------------------*/
198         /* Setup interrupt vectors */
199         /*----------------------------------------------------------------*/
200         mtspr   ivpr,r0         /* Vectors start at 0x0000_0000 */
201         li      r1,0x0100
202         mtspr   ivor0,r1        /* Critical input */
203         li      r1,0x0200
204         mtspr   ivor1,r1        /* Machine check */
205         li      r1,0x0300
206         mtspr   ivor2,r1        /* Data storage */
207         li      r1,0x0400
208         mtspr   ivor3,r1        /* Instruction storage */
209         li      r1,0x0500
210         mtspr   ivor4,r1        /* External interrupt */
211         li      r1,0x0600
212         mtspr   ivor5,r1        /* Alignment */
213         li      r1,0x0700
214         mtspr   ivor6,r1        /* Program check */
215         li      r1,0x0800
216         mtspr   ivor7,r1        /* Floating point unavailable */
217         li      r1,0x0c00
218         mtspr   ivor8,r1        /* System call */
219         li      r1,0x1000
220         mtspr   ivor10,r1       /* Decrementer (PIT for 440) */
221         li      r1,0x1400
222         mtspr   ivor13,r1       /* Data TLB error */
223         li      r1,0x1300
224         mtspr   ivor14,r1       /* Instr TLB error */
225         li      r1,0x2000
226         mtspr   ivor15,r1       /* Debug */
227
228         /*----------------------------------------------------------------*/
229         /* Configure cache regions  */
230         /*----------------------------------------------------------------*/
231         mtspr   inv0,r0
232         mtspr   inv1,r0
233         mtspr   inv2,r0
234         mtspr   inv3,r0
235         mtspr   dnv0,r0
236         mtspr   dnv1,r0
237         mtspr   dnv2,r0
238         mtspr   dnv3,r0
239         mtspr   itv0,r0
240         mtspr   itv1,r0
241         mtspr   itv2,r0
242         mtspr   itv3,r0
243         mtspr   dtv0,r0
244         mtspr   dtv1,r0
245         mtspr   dtv2,r0
246         mtspr   dtv3,r0
247
248         /*----------------------------------------------------------------*/
249         /* Cache victim limits */
250         /*----------------------------------------------------------------*/
251         /* floors 0, ceiling max to use the entire cache -- nothing locked
252         */
253         lis     r1,0x0001
254         ori     r1,r1,0xf800
255         mtspr   ivlim,r1
256         mtspr   dvlim,r1
257
258         /*----------------------------------------------------------------*/
259         /* Clear all TLB entries -- TID = 0, TS = 0 */
260         /*----------------------------------------------------------------*/
261         mtspr   mmucr,r0
262         li      r1,0x003f       /* 64 TLB entries */
263         mtctr   r1
264 0:      tlbwe   r0,r1,0x0000    /* Invalidate all entries (V=0)*/
265         subi    r1,r1,0x0001
266         bdnz    0b
267
268         /*----------------------------------------------------------------*/
269         /* TLB entry setup -- step thru tlbtab */
270         /*----------------------------------------------------------------*/
271         bl      tlbtab          /* Get tlbtab pointer */
272         mr      r5,r0
273         li      r1,0x003f       /* 64 TLB entries max */
274         mtctr   r1
275         li      r4,0            /* TLB # */
276
277         addi    r5,r5,-4
278 1:      lwzu    r0,4(r5)
279         cmpwi   r0,0
280         beq     2f              /* 0 marks end */
281         lwzu    r1,4(r5)
282         lwzu    r2,4(r5)
283         tlbwe   r0,r4,0         /* TLB Word 0 */
284         tlbwe   r1,r4,1         /* TLB Word 1 */
285         tlbwe   r2,r4,2         /* TLB Word 2 */
286         addi    r4,r4,1         /* Next TLB */
287         bdnz    1b
288
289         /*----------------------------------------------------------------*/
290         /* Continue from 'normal' start */
291         /*----------------------------------------------------------------*/
292 2:      bl      3f
293         b       _start
294
295 3:      li      r0,0
296         mtspr   srr1,r0         /* Keep things disabled for now */
297         mflr    r1
298         mtspr   srr0,r1
299         rfi
300 #endif
301
302 /*
303  * r3 - 1st arg to board_init(): IMMP pointer
304  * r4 - 2nd arg to board_init(): boot flag
305  */
306         .text
307         .long   0x27051956              /* U-Boot Magic Number                  */
308         .globl  version_string
309 version_string:
310         .ascii U_BOOT_VERSION
311         .ascii " (", __DATE__, " - ", __TIME__, ")"
312         .ascii CONFIG_IDENT_STRING, "\0"
313
314 /*
315  * Maybe this should be moved somewhere else because the current
316  * location (0x100) is where the CriticalInput Execption should be.
317  */
318         . = EXC_OFF_SYS_RESET
319         .globl  _start
320 _start:
321
322 /*****************************************************************************/
323 #if defined(CONFIG_440)
324
325         /*----------------------------------------------------------------*/
326         /* Clear and set up some registers. */
327         /*----------------------------------------------------------------*/
328         li      r0,0x0000
329         lis     r1,0xffff
330         mtspr   dec,r0                  /* prevent dec exceptions */
331         mtspr   tbl,r0                  /* prevent fit & wdt exceptions */
332         mtspr   tbu,r0
333         mtspr   tsr,r1                  /* clear all timer exception status */
334         mtspr   tcr,r0                  /* disable all */
335         mtspr   esr,r0                  /* clear exception syndrome register */
336         mtxer   r0                      /* clear integer exception register */
337         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
338         ori     r1,r1,0x1000            /* set ME bit (Machine Exceptions) */
339         mtmsr   r1                      /* change MSR */
340
341         /*----------------------------------------------------------------*/
342         /* Debug setup -- some (not very good) ice's need an event*/
343         /* to establish control :-( Define CFG_INIT_DBCR to the dbsr */
344         /* value you need in this case 0x8cff 0000 should do the trick */
345         /*----------------------------------------------------------------*/
346 #if defined(CFG_INIT_DBCR)
347         lis     r1,0xffff
348         ori     r1,r1,0xffff
349         mtspr   dbsr,r1                 /* Clear all status bits */
350         lis     r0,CFG_INIT_DBCR@h
351         ori     r0,r0,CFG_INIT_DBCR@l
352         mtspr   dbcr0,r0
353         isync
354 #endif
355
356         /*----------------------------------------------------------------*/
357         /* Setup the internal SRAM */
358         /*----------------------------------------------------------------*/
359         li      r0,0
360         mtdcr   isram0_sb1cr,r0         /* Disable bank 1 */
361
362         li      r2,0x7fff
363         ori     r2,r2,0xffff
364         mfdcr   r1,isram0_dpc
365         and     r1,r1,r2                /* Disable parity check */
366         mtdcr   isram0_dpc,r1
367         mfdcr   r1,isram0_pmeg
368         andis.  r1,r1,r2                /* Disable pwr mgmt */
369         mtdcr   isram0_pmeg,r1
370
371         lis     r1,0x8000               /* BAS = 8000_0000 */
372         ori     r1,r1,0x0380            /* 8k rw */
373         mtdcr   isram0_sb0cr,r1
374
375         /*----------------------------------------------------------------*/
376         /* Setup the stack in internal SRAM */
377         /*----------------------------------------------------------------*/
378         lis     r1,CFG_INIT_RAM_ADDR@h
379         ori     r1,r1,CFG_INIT_SP_OFFSET@l
380
381         li      r0,0
382         stwu    r0,-4(r1)
383         stwu    r0,-4(r1)               /* Terminate call chain */
384
385         stwu    r1,-8(r1)               /* Save back chain and move SP */
386         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
387         ori     r0,r0, RESET_VECTOR@l
388         stwu    r1,-8(r1)               /* Save back chain and move SP */
389         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
390
391         GET_GOT
392         bl      board_init_f
393
394 #endif /* CONFIG_440 */
395
396 /*****************************************************************************/
397 #ifdef CONFIG_IOP480
398         /*----------------------------------------------------------------------- */
399         /* Set up some machine state registers. */
400         /*----------------------------------------------------------------------- */
401         addi    r0,r0,0x0000            /* initialize r0 to zero */
402         mtspr   esr,r0                  /* clear Exception Syndrome Reg */
403         mttcr   r0                      /* timer control register */
404         mtexier r0                      /* disable all interrupts */
405         addi    r4,r0,0x1000            /* set ME bit (Machine Exceptions) */
406         oris    r4,r4,0x2               /* set CE bit (Critical Exceptions) */
407         mtmsr   r4                      /* change MSR */
408         addis   r4,r0,0xFFFF            /* set r4 to 0xFFFFFFFF (status in the */
409         ori     r4,r4,0xFFFF            /* dbsr is cleared by setting bits to 1) */
410         mtdbsr  r4                      /* clear/reset the dbsr */
411         mtexisr r4                      /* clear all pending interrupts */
412         addis   r4,r0,0x8000
413         mtexier r4                      /* enable critical exceptions */
414         addis   r4,r0,0x0000            /* assume 403GCX - enable core clk */
415         ori     r4,r4,0x4020            /* dbling (no harm done on GA and GC */
416         mtiocr  r4                      /* since bit not used) & DRC to latch */
417                                         /* data bus on rising edge of CAS */
418         /*----------------------------------------------------------------------- */
419         /* Clear XER. */
420         /*----------------------------------------------------------------------- */
421         mtxer   r0
422         /*----------------------------------------------------------------------- */
423         /* Invalidate i-cache and d-cache TAG arrays. */
424         /*----------------------------------------------------------------------- */
425         addi    r3,0,1024               /* 1/4 of I-cache size, half of D-cache */
426         addi    r4,0,1024               /* 1/4 of I-cache */
427 ..cloop:
428         iccci   0,r3
429         iccci   r4,r3
430         dccci   0,r3
431         addic.  r3,r3,-16               /* move back one cache line */
432         bne     ..cloop                 /* loop back to do rest until r3 = 0 */
433
434         /* */
435         /* initialize IOP480 so it can read 1 MB code area for SRAM spaces */
436         /* this requires enabling MA[17..0], by default only MA[12..0] are enabled. */
437         /* */
438
439         /* first copy IOP480 register base address into r3 */
440         addis   r3,0,0x5000             /* IOP480 register base address hi */
441 /*      ori     r3,r3,0x0000            /  IOP480 register base address lo */
442
443 #ifdef CONFIG_ADCIOP
444         /* use r4 as the working variable */
445         /* turn on CS3 (LOCCTL.7) */
446         lwz     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
447         andi.   r4,r4,0xff7f            /* make bit 7 = 0 -- CS3 mode */
448         stw     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
449 #endif
450
451 #ifdef CONFIG_DASA_SIM
452         /* use r4 as the working variable */
453         /* turn on MA17 (LOCCTL.7) */
454         lwz     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
455         ori     r4,r4,0x80              /* make bit 7 = 1 -- MA17 mode */
456         stw     r4,0x84(r3)             /* LOCTL is at offset 0x84 */
457 #endif
458
459         /* turn on MA16..13 (LCS0BRD.12 = 0) */
460         lwz     r4,0x100(r3)            /* LCS0BRD is at offset 0x100 */
461         andi.   r4,r4,0xefff            /* make bit 12 = 0 */
462         stw     r4,0x100(r3)            /* LCS0BRD is at offset 0x100 */
463
464         /* make sure above stores all comlete before going on */
465         sync
466
467         /* last thing, set local init status done bit (DEVINIT.31) */
468         lwz     r4,0x80(r3)             /* DEVINIT is at offset 0x80 */
469         oris    r4,r4,0x8000            /* make bit 31 = 1 */
470         stw     r4,0x80(r3)             /* DEVINIT is at offset 0x80 */
471
472         /* clear all pending interrupts and disable all interrupts */
473         li      r4,-1                   /* set p1 to 0xffffffff */
474         stw     r4,0x1b0(r3)            /* clear all pending interrupts */
475         stw     r4,0x1b8(r3)            /* clear all pending interrupts */
476         li      r4,0                    /* set r4 to 0 */
477         stw     r4,0x1b4(r3)            /* disable all interrupts */
478         stw     r4,0x1bc(r3)            /* disable all interrupts */
479
480         /* make sure above stores all comlete before going on */
481         sync
482
483         /*----------------------------------------------------------------------- */
484         /* Enable two 128MB cachable regions. */
485         /*----------------------------------------------------------------------- */
486         addis   r1,r0,0x8000
487         addi    r1,r1,0x0001
488         mticcr  r1                      /* instruction cache */
489
490         addis   r1,r0,0x0000
491         addi    r1,r1,0x0000
492         mtdccr  r1                      /* data cache */
493
494         addis   r1,r0,CFG_INIT_RAM_ADDR@h
495         ori     r1,r1,CFG_INIT_SP_OFFSET          /* set up the stack to SDRAM */
496         li      r0, 0                   /* Make room for stack frame header and */
497         stwu    r0, -4(r1)              /* clear final stack frame so that      */
498         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
499
500         GET_GOT                 /* initialize GOT access                        */
501
502         bl      board_init_f    /* run first part of init code (from Flash)     */
503
504 #endif  /* CONFIG_IOP480 */
505
506 /*****************************************************************************/
507 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405)
508         /*----------------------------------------------------------------------- */
509         /* Clear and set up some registers. */
510         /*----------------------------------------------------------------------- */
511         addi    r4,r0,0x0000
512         mtspr   sgr,r4
513         mtspr   dcwr,r4
514         mtesr   r4                      /* clear Exception Syndrome Reg */
515         mttcr   r4                      /* clear Timer Control Reg */
516         mtxer   r4                      /* clear Fixed-Point Exception Reg */
517         mtevpr  r4                      /* clear Exception Vector Prefix Reg */
518         addi    r4,r0,0x1000            /* set ME bit (Machine Exceptions) */
519         oris    r4,r4,0x0002            /* set CE bit (Critical Exceptions) */
520         mtmsr   r4                      /* change MSR */
521         addi    r4,r0,(0xFFFF-0x10000)          /* set r4 to 0xFFFFFFFF (status in the */
522                                         /* dbsr is cleared by setting bits to 1) */
523         mtdbsr  r4                      /* clear/reset the dbsr */
524
525         /*----------------------------------------------------------------------- */
526         /* Invalidate I and D caches. Enable I cache for defined memory regions */
527         /* to speed things up. Leave the D cache disabled for now. It will be */
528         /* enabled/left disabled later based on user selected menu options. */
529         /* Be aware that the I cache may be disabled later based on the menu */
530         /* options as well. See miscLib/main.c. */
531         /*----------------------------------------------------------------------- */
532         bl      invalidate_icache
533         bl      invalidate_dcache
534
535         /*----------------------------------------------------------------------- */
536         /* Enable two 128MB cachable regions. */
537         /*----------------------------------------------------------------------- */
538         addis   r4,r0,0x8000
539         addi    r4,r4,0x0001
540         mticcr  r4                      /* instruction cache */
541         isync
542
543         addis   r4,r0,0x0000
544         addi    r4,r4,0x0000
545         mtdccr  r4                      /* data cache */
546
547 #if !(defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
548         /*----------------------------------------------------------------------- */
549         /* Tune the speed and size for flash CS0  */
550         /*----------------------------------------------------------------------- */
551         bl      ext_bus_cntlr_init
552 #endif
553
554 #if defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE)
555         /********************************************************************
556          * Setup OCM - On Chip Memory
557          *******************************************************************/
558         /* Setup OCM */
559         lis     r0, 0x7FFF
560         ori     r0, r0, 0xFFFF
561         mfdcr   r3, ocmiscntl           /* get instr-side IRAM config */
562         mfdcr   r4, ocmdscntl   /* get data-side IRAM config */
563         and     r3, r3, r0      /* disable data-side IRAM */
564         and     r4, r4, r0      /* disable data-side IRAM */
565         mtdcr   ocmiscntl, r3   /* set instr-side IRAM config */
566         mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
567         isync
568
569         addis   r3, 0, CFG_OCM_DATA_ADDR@h /* OCM location */
570         mtdcr   ocmdsarc, r3
571         addis   r4, 0, 0xC000           /* OCM data area enabled */
572         mtdcr   ocmdscntl, r4
573         isync
574 #endif
575
576         /*----------------------------------------------------------------------- */
577         /* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */
578         /*----------------------------------------------------------------------- */
579 #ifdef CFG_INIT_DCACHE_CS
580         /*----------------------------------------------------------------------- */
581         /* Memory Bank x (nothingness) initialization 1GB+64MEG */
582         /* used as temporary stack pointer for stage0  */
583         /*----------------------------------------------------------------------- */
584         li      r4,PBxAP
585         mtdcr   ebccfga,r4
586         lis     r4,0x0380
587         ori     r4,r4,0x0480
588         mtdcr   ebccfgd,r4
589
590         addi    r4,0,PBxCR
591         mtdcr   ebccfga,r4
592         lis     r4,0x400D
593         ori     r4,r4,0xa000
594         mtdcr   ebccfgd,r4
595
596         /* turn on data chache for this region */
597         lis     r4,0x0080
598         mtdccr  r4
599
600         /* set stack pointer and clear stack to known value */
601
602         lis     r1,CFG_INIT_RAM_ADDR@h
603         ori     r1,r1,CFG_INIT_SP_OFFSET@l
604
605         li      r4,2048                 /* we store 2048 words to stack */
606         mtctr   r4
607
608         lis     r2,CFG_INIT_RAM_ADDR@h          /* we also clear data area */
609         ori     r2,r2,CFG_INIT_RAM_END@l        /* so cant copy value from r1 */
610
611         lis     r4,0xdead               /* we store 0xdeaddead in the stack */
612         ori     r4,r4,0xdead
613
614 ..stackloop:
615         stwu    r4,-4(r2)
616         bdnz    ..stackloop
617
618         li      r0, 0                   /* Make room for stack frame header and */
619         stwu    r0, -4(r1)              /* clear final stack frame so that      */
620         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
621         /*
622          * Set up a dummy frame to store reset vector as return address.
623          * this causes stack underflow to reset board.
624          */
625         stwu    r1, -8(r1)              /* Save back chain and move SP */
626         addis   r0, 0, RESET_VECTOR@h   /* Address of reset vector */
627         ori     r0, r0, RESET_VECTOR@l
628         stwu    r1, -8(r1)              /* Save back chain and move SP */
629         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
630
631 #elif defined(CFG_TEMP_STACK_OCM) && \
632         (defined(CFG_OCM_DATA_ADDR) && defined(CFG_OCM_DATA_SIZE))
633         /*
634          * Stack in OCM.
635          */
636
637         /* Set up Stack at top of OCM */
638         lis     r1, (CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET)@h
639         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET)@l
640
641         /* Set up a zeroized stack frame so that backtrace works right */
642         li      r0, 0
643         stwu    r0, -4(r1)
644         stwu    r0, -4(r1)
645
646         /*
647          * Set up a dummy frame to store reset vector as return address.
648          * this causes stack underflow to reset board.
649          */
650         stwu    r1, -8(r1)              /* Save back chain and move SP */
651         lis     r0, RESET_VECTOR@h      /* Address of reset vector */
652         ori     r0, r0, RESET_VECTOR@l
653         stwu    r1, -8(r1)              /* Save back chain and move SP */
654         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
655 #endif /* CFG_INIT_DCACHE_CS */
656
657         /*----------------------------------------------------------------------- */
658         /* Initialize SDRAM Controller  */
659         /*----------------------------------------------------------------------- */
660         bl      sdram_init
661
662         /*
663          * Setup temporary stack pointer only for boards
664          * that do not use SDRAM SPD I2C stuff since it
665          * is already initialized to use DCACHE or OCM
666          * stacks.
667          */
668 #if !(defined(CFG_INIT_DCACHE_CS) || defined(CFG_TEMP_STACK_OCM))
669         lis     r1, CFG_INIT_RAM_ADDR@h
670         ori     r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */
671
672         li      r0, 0                   /* Make room for stack frame header and */
673         stwu    r0, -4(r1)              /* clear final stack frame so that      */
674         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
675         /*
676          * Set up a dummy frame to store reset vector as return address.
677          * this causes stack underflow to reset board.
678          */
679         stwu    r1, -8(r1)              /* Save back chain and move SP */
680         lis     r0, RESET_VECTOR@h      /* Address of reset vector */
681         ori     r0, r0, RESET_VECTOR@l
682         stwu    r1, -8(r1)              /* Save back chain and move SP */
683         stw     r0, +12(r1)             /* Save return addr (underflow vect) */
684 #endif /* !(CFG_INIT_DCACHE_CS  || !CFG_TEM_STACK_OCM) */
685
686         GET_GOT                 /* initialize GOT access                        */
687
688         bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
689
690         /* NEVER RETURNS! */
691         bl      board_init_f    /* run first part of init code (from Flash)     */
692
693 #endif  /* CONFIG_405GP || CONFIG_405CR */
694
695
696         .globl  _start_of_vectors
697 _start_of_vectors:
698
699 #if 0
700 /*TODO Fixup _start above so we can do this*/
701 /* Critical input. */
702         CRIT_EXCEPTION(0x100, CritcalInput, CritcalInputException)
703 #endif
704
705 /* Machine check */
706         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
707
708 /* Data Storage exception. */
709         STD_EXCEPTION(0x300, DataStorage, UnknownException)
710
711 /* Instruction Storage exception. */
712         STD_EXCEPTION(0x400, InstStorage, UnknownException)
713
714 /* External Interrupt exception. */
715         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
716
717 /* Alignment exception. */
718         . = 0x600
719 Alignment:
720         EXCEPTION_PROLOG
721         mfspr   r4,DAR
722         stw     r4,_DAR(r21)
723         mfspr   r5,DSISR
724         stw     r5,_DSISR(r21)
725         addi    r3,r1,STACK_FRAME_OVERHEAD
726         li      r20,MSR_KERNEL
727         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
728         lwz     r6,GOT(transfer_to_handler)
729         mtlr    r6
730         blrl
731 .L_Alignment:
732         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
733         .long   int_return - _start + EXC_OFF_SYS_RESET
734
735 /* Program check exception */
736         . = 0x700
737 ProgramCheck:
738         EXCEPTION_PROLOG
739         addi    r3,r1,STACK_FRAME_OVERHEAD
740         li      r20,MSR_KERNEL
741         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
742         lwz     r6,GOT(transfer_to_handler)
743         mtlr    r6
744         blrl
745 .L_ProgramCheck:
746         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
747         .long   int_return - _start + EXC_OFF_SYS_RESET
748
749         /* No FPU on MPC8xx.  This exception is not supposed to happen.
750         */
751         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
752
753         /* I guess we could implement decrementer, and may have
754          * to someday for timekeeping.
755          */
756         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
757         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
758         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
759
760         . = 0xc00
761 /*
762  * r0 - SYSCALL number
763  * r3-... arguments
764  */
765 SystemCall:
766         addis   r11,r0,0                /* get functions table addr */
767         ori     r11,r11,0               /* Note: this code is patched in trap_init */
768         addis   r12,r0,0                /* get number of functions */
769         ori     r12,r12,0
770
771         cmplw   0, r0, r12
772         bge     1f
773
774         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
775         add     r11,r11,r0
776         lwz     r11,0(r11)
777
778         li      r20,0xd00-4             /* Get stack pointer */
779         lwz     r12,0(r20)
780         subi    r12,r12,12              /* Adjust stack pointer */
781         li      r0,0xc00+_end_back-SystemCall
782         cmplw   0, r0, r12              /* Check stack overflow */
783         bgt     1f
784         stw     r12,0(r20)
785
786         mflr    r0
787         stw     r0,0(r12)
788         mfspr   r0,SRR0
789         stw     r0,4(r12)
790         mfspr   r0,SRR1
791         stw     r0,8(r12)
792
793         li      r12,0xc00+_back-SystemCall
794         mtlr    r12
795         mtspr   SRR0,r11
796
797 1:      SYNC
798         rfi
799
800 _back:
801
802         mfmsr   r11                     /* Disable interrupts */
803         li      r12,0
804         ori     r12,r12,MSR_EE
805         andc    r11,r11,r12
806         SYNC                            /* Some chip revs need this... */
807         mtmsr   r11
808         SYNC
809
810         li      r12,0xd00-4             /* restore regs */
811         lwz     r12,0(r12)
812
813         lwz     r11,0(r12)
814         mtlr    r11
815         lwz     r11,4(r12)
816         mtspr   SRR0,r11
817         lwz     r11,8(r12)
818         mtspr   SRR1,r11
819
820         addi    r12,r12,12              /* Adjust stack pointer */
821         li      r20,0xd00-4
822         stw     r12,0(r20)
823
824         SYNC
825         rfi
826 _end_back:
827
828         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
829
830         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
831         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
832
833         /* On the MPC8xx, this is a software emulation interrupt.  It occurs
834          * for all unimplemented and illegal instructions.
835          */
836         STD_EXCEPTION(0x1000, PIT, PITException)
837
838         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
839         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
840         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
841         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
842
843         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
844         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
845         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
846         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
847         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
848         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
849         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
850
851         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
852         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
853         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
854         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
855
856         CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
857
858         .globl  _end_of_vectors
859 _end_of_vectors:
860
861
862         . = 0x2100
863
864 /*
865  * This code finishes saving the registers to the exception frame
866  * and jumps to the appropriate handler for the exception.
867  * Register r21 is pointer into trap frame, r1 has new stack pointer.
868  */
869         .globl  transfer_to_handler
870 transfer_to_handler:
871         stw     r22,_NIP(r21)
872         lis     r22,MSR_POW@h
873         andc    r23,r23,r22
874         stw     r23,_MSR(r21)
875         SAVE_GPR(7, r21)
876         SAVE_4GPRS(8, r21)
877         SAVE_8GPRS(12, r21)
878         SAVE_8GPRS(24, r21)
879 #if 0
880         andi.   r23,r23,MSR_PR
881         mfspr   r23,SPRG3               /* if from user, fix up tss.regs */
882         beq     2f
883         addi    r24,r1,STACK_FRAME_OVERHEAD
884         stw     r24,PT_REGS(r23)
885 2:      addi    r2,r23,-TSS             /* set r2 to current */
886         tovirt(r2,r2,r23)
887 #endif
888         mflr    r23
889         andi.   r24,r23,0x3f00          /* get vector offset */
890         stw     r24,TRAP(r21)
891         li      r22,0
892         stw     r22,RESULT(r21)
893         mtspr   SPRG2,r22               /* r1 is now kernel sp */
894 #if 0
895         addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
896         cmplw   0,r1,r2
897         cmplw   1,r1,r24
898         crand   1,1,4
899         bgt     stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
900 #endif
901         lwz     r24,0(r23)              /* virtual address of handler */
902         lwz     r23,4(r23)              /* where to go when done */
903         mtspr   SRR0,r24
904         mtspr   SRR1,r20
905         mtlr    r23
906         SYNC
907         rfi                             /* jump to handler, enable MMU */
908
909 int_return:
910         mfmsr   r28             /* Disable interrupts */
911         li      r4,0
912         ori     r4,r4,MSR_EE
913         andc    r28,r28,r4
914         SYNC                    /* Some chip revs need this... */
915         mtmsr   r28
916         SYNC
917         lwz     r2,_CTR(r1)
918         lwz     r0,_LINK(r1)
919         mtctr   r2
920         mtlr    r0
921         lwz     r2,_XER(r1)
922         lwz     r0,_CCR(r1)
923         mtspr   XER,r2
924         mtcrf   0xFF,r0
925         REST_10GPRS(3, r1)
926         REST_10GPRS(13, r1)
927         REST_8GPRS(23, r1)
928         REST_GPR(31, r1)
929         lwz     r2,_NIP(r1)     /* Restore environment */
930         lwz     r0,_MSR(r1)
931         mtspr   SRR0,r2
932         mtspr   SRR1,r0
933         lwz     r0,GPR0(r1)
934         lwz     r2,GPR2(r1)
935         lwz     r1,GPR1(r1)
936         SYNC
937         rfi
938
939 crit_return:
940         mfmsr   r28             /* Disable interrupts */
941         li      r4,0
942         ori     r4,r4,MSR_EE
943         andc    r28,r28,r4
944         SYNC                    /* Some chip revs need this... */
945         mtmsr   r28
946         SYNC
947         lwz     r2,_CTR(r1)
948         lwz     r0,_LINK(r1)
949         mtctr   r2
950         mtlr    r0
951         lwz     r2,_XER(r1)
952         lwz     r0,_CCR(r1)
953         mtspr   XER,r2
954         mtcrf   0xFF,r0
955         REST_10GPRS(3, r1)
956         REST_10GPRS(13, r1)
957         REST_8GPRS(23, r1)
958         REST_GPR(31, r1)
959         lwz     r2,_NIP(r1)     /* Restore environment */
960         lwz     r0,_MSR(r1)
961         mtspr   990,r2          /* SRR2 */
962         mtspr   991,r0          /* SRR3 */
963         lwz     r0,GPR0(r1)
964         lwz     r2,GPR2(r1)
965         lwz     r1,GPR1(r1)
966         SYNC
967         rfci
968
969 /* Cache functions.
970 */
971 invalidate_icache:
972         iccci   r0,r0                   /* for 405, iccci invalidates the */
973         blr                             /*   entire I cache */
974
975 invalidate_dcache:
976         addi    r6,0,0x0000             /* clear GPR 6 */
977         /* Do loop for # of dcache congruence classes. */
978         addi    r7,r0, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
979                                         /* NOTE: dccci invalidates both */
980         mtctr   r7                      /* ways in the D cache */
981 ..dcloop:
982         dccci   0,r6                    /* invalidate line */
983         addi    r6,r6, CFG_CACHELINE_SIZE /* bump to next line */
984         bdnz    ..dcloop
985         blr
986
987 flush_dcache:
988         addis   r9,r0,0x0002            /* set mask for EE and CE msr bits */
989         ori     r9,r9,0x8000
990         mfmsr   r12                     /* save msr */
991         andc    r9,r12,r9
992         mtmsr   r9                      /* disable EE and CE */
993         addi    r10,r0,0x0001           /* enable data cache for unused memory */
994         mfdccr  r9                      /* region 0xF8000000-0xFFFFFFFF via */
995         or      r10,r10,r9              /* bit 31 in dccr */
996         mtdccr  r10
997
998         /* do loop for # of congruence classes. */
999         addi    r10,r0,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)
1000         addi    r11,r0,(CFG_DCACHE_SIZE / 2) /* D cache set size - 2 way sets */
1001         mtctr   r10
1002         addi    r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */
1003         add     r11,r10,r11             /* add to get to other side of cache line */
1004 ..flush_dcache_loop:
1005         lwz     r3,0(r10)               /* least recently used side */
1006         lwz     r3,0(r11)               /* the other side */
1007         dccci   r0,r11                  /* invalidate both sides */
1008         addi    r10,r10,CFG_CACHELINE_SIZE /* bump to next line */
1009         addi    r11,r11,CFG_CACHELINE_SIZE /* bump to next line */
1010         bdnz    ..flush_dcache_loop
1011         sync                            /* allow memory access to complete */
1012         mtdccr  r9                      /* restore dccr */
1013         mtmsr   r12                     /* restore msr */
1014         blr
1015
1016         .globl  icache_enable
1017 icache_enable:
1018         mflr    r8
1019         bl      invalidate_icache
1020         mtlr    r8
1021         isync
1022         addis   r3,r0, 0x8000         /* set bit 0 */
1023         mticcr  r3
1024         blr
1025
1026         .globl  icache_disable
1027 icache_disable:
1028         addis   r3,r0, 0x0000         /* clear bit 0 */
1029         mticcr  r3
1030         isync
1031         blr
1032
1033         .globl  icache_status
1034 icache_status:
1035         mficcr  r3
1036         srwi    r3, r3, 31      /* >>31 => select bit 0 */
1037         blr
1038
1039         .globl  dcache_enable
1040 dcache_enable:
1041         mflr    r8
1042         bl      invalidate_dcache
1043         mtlr    r8
1044         isync
1045         addis   r3,r0, 0x8000         /* set bit 0 */
1046         mtdccr  r3
1047         blr
1048
1049         .globl  dcache_disable
1050 dcache_disable:
1051         mflr    r8
1052         bl      flush_dcache
1053         mtlr    r8
1054         addis   r3,r0, 0x0000         /* clear bit 0 */
1055         mtdccr  r3
1056         blr
1057
1058         .globl  dcache_status
1059 dcache_status:
1060         mfdccr  r3
1061         srwi    r3, r3, 31      /* >>31 => select bit 0 */
1062         blr
1063
1064         .globl get_pvr
1065 get_pvr:
1066         mfspr   r3, PVR
1067         blr
1068
1069 #if !defined(CONFIG_440)
1070         .globl wr_pit
1071 wr_pit:
1072         mtspr   pit, r3
1073         blr
1074 #endif
1075
1076         .globl wr_tcr
1077 wr_tcr:
1078         mtspr   tcr, r3
1079         blr
1080
1081 /*------------------------------------------------------------------------------- */
1082 /* Function:     in8 */
1083 /* Description:  Input 8 bits */
1084 /*------------------------------------------------------------------------------- */
1085         .globl  in8
1086 in8:
1087         lbz     r3,0x0000(r3)
1088         blr
1089
1090 /*------------------------------------------------------------------------------- */
1091 /* Function:     out8 */
1092 /* Description:  Output 8 bits */
1093 /*------------------------------------------------------------------------------- */
1094         .globl  out8
1095 out8:
1096         stb     r4,0x0000(r3)
1097         blr
1098
1099 /*------------------------------------------------------------------------------- */
1100 /* Function:     out16 */
1101 /* Description:  Output 16 bits */
1102 /*------------------------------------------------------------------------------- */
1103         .globl  out16
1104 out16:
1105         sth     r4,0x0000(r3)
1106         blr
1107
1108 /*------------------------------------------------------------------------------- */
1109 /* Function:     out16r */
1110 /* Description:  Byte reverse and output 16 bits */
1111 /*------------------------------------------------------------------------------- */
1112         .globl  out16r
1113 out16r:
1114         sthbrx  r4,r0,r3
1115         blr
1116
1117 /*------------------------------------------------------------------------------- */
1118 /* Function:     out32 */
1119 /* Description:  Output 32 bits */
1120 /*------------------------------------------------------------------------------- */
1121         .globl  out32
1122 out32:
1123         stw     r4,0x0000(r3)
1124         blr
1125
1126 /*------------------------------------------------------------------------------- */
1127 /* Function:     out32r */
1128 /* Description:  Byte reverse and output 32 bits */
1129 /*------------------------------------------------------------------------------- */
1130         .globl  out32r
1131 out32r:
1132         stwbrx  r4,r0,r3
1133         blr
1134
1135 /*------------------------------------------------------------------------------- */
1136 /* Function:     in16 */
1137 /* Description:  Input 16 bits */
1138 /*------------------------------------------------------------------------------- */
1139         .globl  in16
1140 in16:
1141         lhz     r3,0x0000(r3)
1142         blr
1143
1144 /*------------------------------------------------------------------------------- */
1145 /* Function:     in16r */
1146 /* Description:  Input 16 bits and byte reverse */
1147 /*------------------------------------------------------------------------------- */
1148         .globl  in16r
1149 in16r:
1150         lhbrx   r3,r0,r3
1151         blr
1152
1153 /*------------------------------------------------------------------------------- */
1154 /* Function:     in32 */
1155 /* Description:  Input 32 bits */
1156 /*------------------------------------------------------------------------------- */
1157         .globl  in32
1158 in32:
1159         lwz     3,0x0000(3)
1160         blr
1161
1162 /*------------------------------------------------------------------------------- */
1163 /* Function:     in32r */
1164 /* Description:  Input 32 bits and byte reverse */
1165 /*------------------------------------------------------------------------------- */
1166         .globl  in32r
1167 in32r:
1168         lwbrx   r3,r0,r3
1169         blr
1170
1171 /*------------------------------------------------------------------------------- */
1172 /* Function:     ppcDcbf */
1173 /* Description:  Data Cache block flush */
1174 /* Input:        r3 = effective address */
1175 /* Output:       none. */
1176 /*------------------------------------------------------------------------------- */
1177         .globl  ppcDcbf
1178 ppcDcbf:
1179         dcbf    r0,r3
1180         blr
1181
1182 /*------------------------------------------------------------------------------- */
1183 /* Function:     ppcDcbi */
1184 /* Description:  Data Cache block Invalidate */
1185 /* Input:        r3 = effective address */
1186 /* Output:       none. */
1187 /*------------------------------------------------------------------------------- */
1188         .globl  ppcDcbi
1189 ppcDcbi:
1190         dcbi    r0,r3
1191         blr
1192
1193 /*------------------------------------------------------------------------------- */
1194 /* Function:     ppcSync */
1195 /* Description:  Processor Synchronize */
1196 /* Input:        none. */
1197 /* Output:       none. */
1198 /*------------------------------------------------------------------------------- */
1199         .globl  ppcSync
1200 ppcSync:
1201         sync
1202         blr
1203
1204 /*------------------------------------------------------------------------------*/
1205
1206 /*
1207  * void relocate_code (addr_sp, gd, addr_moni)
1208  *
1209  * This "function" does not return, instead it continues in RAM
1210  * after relocating the monitor code.
1211  *
1212  * r3 = dest
1213  * r4 = src
1214  * r5 = length in bytes
1215  * r6 = cachelinesize
1216  */
1217         .globl  relocate_code
1218 relocate_code:
1219         mr      r1,  r3         /* Set new stack pointer                */
1220         mr      r9,  r4         /* Save copy of Init Data pointer       */
1221         mr      r10, r5         /* Save copy of Destination Address     */
1222
1223         mr      r3,  r5                         /* Destination Address  */
1224         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
1225         ori     r4, r4, CFG_MONITOR_BASE@l
1226         lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
1227         ori     r5, r5, CFG_MONITOR_LEN@l
1228         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
1229
1230         /*
1231          * Fix GOT pointer:
1232          *
1233          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
1234          *
1235          * Offset:
1236          */
1237         sub     r15, r10, r4
1238
1239         /* First our own GOT */
1240         add     r14, r14, r15
1241         /* the the one used by the C code */
1242         add     r30, r30, r15
1243
1244         /*
1245          * Now relocate code
1246          */
1247
1248         cmplw   cr1,r3,r4
1249         addi    r0,r5,3
1250         srwi.   r0,r0,2
1251         beq     cr1,4f          /* In place copy is not necessary       */
1252         beq     7f              /* Protect against 0 count              */
1253         mtctr   r0
1254         bge     cr1,2f
1255
1256         la      r8,-4(r4)
1257         la      r7,-4(r3)
1258 1:      lwzu    r0,4(r8)
1259         stwu    r0,4(r7)
1260         bdnz    1b
1261         b       4f
1262
1263 2:      slwi    r0,r0,2
1264         add     r8,r4,r0
1265         add     r7,r3,r0
1266 3:      lwzu    r0,-4(r8)
1267         stwu    r0,-4(r7)
1268         bdnz    3b
1269
1270 /*
1271  * Now flush the cache: note that we must start from a cache aligned
1272  * address. Otherwise we might miss one cache line.
1273  */
1274 4:      cmpwi   r6,0
1275         add     r5,r3,r5
1276         beq     7f              /* Always flush prefetch queue in any case */
1277         subi    r0,r6,1
1278         andc    r3,r3,r0
1279         mr      r4,r3
1280 5:      dcbst   0,r4
1281         add     r4,r4,r6
1282         cmplw   r4,r5
1283         blt     5b
1284         sync                    /* Wait for all dcbst to complete on bus */
1285         mr      r4,r3
1286 6:      icbi    0,r4
1287         add     r4,r4,r6
1288         cmplw   r4,r5
1289         blt     6b
1290 7:      sync                    /* Wait for all icbi to complete on bus */
1291         isync
1292
1293 /*
1294  * We are done. Do not return, instead branch to second part of board
1295  * initialization, now running from RAM.
1296  */
1297
1298         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1299         mtlr    r0
1300         blr                             /* NEVER RETURNS! */
1301
1302 in_ram:
1303
1304         /*
1305          * Relocation Function, r14 point to got2+0x8000
1306          *
1307          * Adjust got2 pointers, no need to check for 0, this code
1308          * already puts a few entries in the table.
1309          */
1310         li      r0,__got2_entries@sectoff@l
1311         la      r3,GOT(_GOT2_TABLE_)
1312         lwz     r11,GOT(_GOT2_TABLE_)
1313         mtctr   r0
1314         sub     r11,r3,r11
1315         addi    r3,r3,-4
1316 1:      lwzu    r0,4(r3)
1317         add     r0,r0,r11
1318         stw     r0,0(r3)
1319         bdnz    1b
1320
1321         /*
1322          * Now adjust the fixups and the pointers to the fixups
1323          * in case we need to move ourselves again.
1324          */
1325 2:      li      r0,__fixup_entries@sectoff@l
1326         lwz     r3,GOT(_FIXUP_TABLE_)
1327         cmpwi   r0,0
1328         mtctr   r0
1329         addi    r3,r3,-4
1330         beq     4f
1331 3:      lwzu    r4,4(r3)
1332         lwzux   r0,r4,r11
1333         add     r0,r0,r11
1334         stw     r10,0(r3)
1335         stw     r0,0(r4)
1336         bdnz    3b
1337 4:
1338 clear_bss:
1339         /*
1340          * Now clear BSS segment
1341          */
1342         lwz     r3,GOT(.bss)
1343         lwz     r4,GOT(_end)
1344
1345         cmplw   0, r3, r4
1346         beq     6f
1347
1348         li      r0, 0
1349 5:
1350         stw     r0, 0(r3)
1351         addi    r3, r3, 4
1352         cmplw   0, r3, r4
1353         bne     5b
1354 6:
1355
1356         mr      r3, r9          /* Init Data pointer            */
1357         mr      r4, r10         /* Destination Address          */
1358         bl      board_init_r
1359
1360         /* Problems accessing "end" in C, so do it here */
1361         .globl  get_endaddr
1362 get_endaddr:
1363         lwz     r3,GOT(_end)
1364         blr
1365
1366         /*
1367          * Copy exception vector code to low memory
1368          *
1369          * r3: dest_addr
1370          * r7: source address, r8: end address, r9: target address
1371          */
1372         .globl  trap_init
1373 trap_init:
1374         lwz     r7, GOT(_start)
1375         lwz     r8, GOT(_end_of_vectors)
1376
1377         rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
1378
1379         cmplw   0, r7, r8
1380         bgelr                           /* return if r7>=r8 - just in case */
1381
1382         mflr    r4                      /* save link register           */
1383 1:
1384         lwz     r0, 0(r7)
1385         stw     r0, 0(r9)
1386         addi    r7, r7, 4
1387         addi    r9, r9, 4
1388         cmplw   0, r7, r8
1389         bne     1b
1390
1391         /*
1392          * relocate `hdlr' and `int_return' entries
1393          */
1394         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1395         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
1396 2:
1397         bl      trap_reloc
1398         addi    r7, r7, 0x100           /* next exception vector        */
1399         cmplw   0, r7, r8
1400         blt     2b
1401
1402         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1403         bl      trap_reloc
1404
1405         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1406         bl      trap_reloc
1407
1408         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1409         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1410 3:
1411         bl      trap_reloc
1412         addi    r7, r7, 0x100           /* next exception vector        */
1413         cmplw   0, r7, r8
1414         blt     3b
1415
1416         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1417         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1418 4:
1419         bl      trap_reloc
1420         addi    r7, r7, 0x100           /* next exception vector        */
1421         cmplw   0, r7, r8
1422         blt     4b
1423
1424         mtlr    r4                      /* restore link register        */
1425         blr
1426
1427         /*
1428          * Function: relocate entries for one exception vector
1429          */
1430 trap_reloc:
1431         lwz     r0, 0(r7)               /* hdlr ...                     */
1432         add     r0, r0, r3              /*  ... += dest_addr            */
1433         stw     r0, 0(r7)
1434
1435         lwz     r0, 4(r7)               /* int_return ...               */
1436         add     r0, r0, r3              /*  ... += dest_addr            */
1437         stw     r0, 4(r7)
1438
1439         blr