]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc86xx/start.S
Merge branch 'mpc86xx'
[karo-tx-uboot.git] / cpu / mpc86xx / start.S
1 /*
2  * Copyright 2004 Freescale Semiconductor.
3  * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
25  *
26  *
27  *  The processor starts at 0xfff00100 and the code is executed
28  *  from flash. The code is organized to be at an other address
29  *  in memory, but as long we don't jump around before relocating.
30  *  board_init lies at a quite high address and when the cpu has
31  *  jumped there, everything is ok.
32  */
33 #include <config.h>
34 #include <mpc86xx.h>
35 #include <version.h>
36
37 #include <ppc_asm.tmpl>
38 #include <ppc_defs.h>
39
40 #include <asm/cache.h>
41 #include <asm/mmu.h>
42
43 #ifndef  CONFIG_IDENT_STRING
44 #define  CONFIG_IDENT_STRING ""
45 #endif
46
47 /* We don't want the  MMU yet.
48 */
49 #undef  MSR_KERNEL
50 /* Machine Check and Recoverable Interr. */
51 #define MSR_KERNEL ( MSR_ME | MSR_RI )
52
53 /*
54  * Set up GOT: Global Offset Table
55  *
56  * Use r14 to access the GOT
57  */
58         START_GOT
59         GOT_ENTRY(_GOT2_TABLE_)
60         GOT_ENTRY(_FIXUP_TABLE_)
61
62         GOT_ENTRY(_start)
63         GOT_ENTRY(_start_of_vectors)
64         GOT_ENTRY(_end_of_vectors)
65         GOT_ENTRY(transfer_to_handler)
66
67         GOT_ENTRY(__init_end)
68         GOT_ENTRY(_end)
69         GOT_ENTRY(__bss_start)
70         END_GOT
71
72 /*
73  * r3 - 1st arg to board_init(): IMMP pointer
74  * r4 - 2nd arg to board_init(): boot flag
75  */
76         .text
77         .long   0x27051956              /* U-Boot Magic Number          */
78         .globl  version_string
79 version_string:
80         .ascii  U_BOOT_VERSION
81         .ascii  " (", __DATE__, " - ", __TIME__, ")"
82         .ascii  CONFIG_IDENT_STRING, "\0"
83
84         . = EXC_OFF_SYS_RESET
85         .globl  _start
86 _start:
87         li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
88         b       boot_cold
89         sync
90
91         . = EXC_OFF_SYS_RESET + 0x10
92
93         .globl  _start_warm
94 _start_warm:
95         li      r21, BOOTFLAG_WARM      /* Software reboot              */
96         b       boot_warm
97         sync
98
99         /* the boot code is located below the exception table */
100
101         .globl  _start_of_vectors
102 _start_of_vectors:
103
104 /* Machine check */
105         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
106
107 /* Data Storage exception. */
108         STD_EXCEPTION(0x300, DataStorage, UnknownException)
109
110 /* Instruction Storage exception. */
111         STD_EXCEPTION(0x400, InstStorage, UnknownException)
112
113 /* External Interrupt exception. */
114         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
115
116 /* Alignment exception. */
117         . = 0x600
118 Alignment:
119         EXCEPTION_PROLOG
120         mfspr   r4,DAR
121         stw     r4,_DAR(r21)
122         mfspr   r5,DSISR
123         stw     r5,_DSISR(r21)
124         addi    r3,r1,STACK_FRAME_OVERHEAD
125         li      r20,MSR_KERNEL
126         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
127         lwz     r6,GOT(transfer_to_handler)
128         mtlr    r6
129         blrl
130 .L_Alignment:
131         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
132         .long   int_return - _start + EXC_OFF_SYS_RESET
133
134 /* Program check exception */
135         . = 0x700
136 ProgramCheck:
137         EXCEPTION_PROLOG
138         addi    r3,r1,STACK_FRAME_OVERHEAD
139         li      r20,MSR_KERNEL
140         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
141         lwz     r6,GOT(transfer_to_handler)
142         mtlr    r6
143         blrl
144 .L_ProgramCheck:
145         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
146         .long   int_return - _start + EXC_OFF_SYS_RESET
147
148         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
149
150         /* I guess we could implement decrementer, and may have
151          * to someday for timekeeping.
152          */
153         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
154         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
155         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
156         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
157         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
158         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
159         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
160         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
161         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
162         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
163         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
164         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
165         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
166         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
167         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
168         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
169         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
170         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
171         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
172         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
173         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
174         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
175         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
176
177         .globl  _end_of_vectors
178 _end_of_vectors:
179
180         . = 0x2000
181
182 boot_cold:
183 boot_warm:
184
185         /* if this is a multi-core system we need to check which cpu
186          * this is, if it is not cpu 0 send the cpu to the linux reset 
187          * vector */
188 #if (CONFIG_NUM_CPUS > 1)
189         mfspr   r0, MSSCR0
190         andi.   r0, r0, 0x0020
191         rlwinm  r0,r0,27,31,31
192         mtspr   PIR, r0
193         beq     1f
194
195         bl      secondary_cpu_setup
196 #endif
197         
198         /* disable everything */
199 1:      li      r0, 0
200         mtspr   HID0, r0
201         sync
202         mtmsr   0
203         bl      invalidate_bats
204         sync
205         
206 #ifdef CFG_L2
207         /* init the L2 cache */
208         addis   r3, r0, L2_INIT@h
209         ori     r3, r3, L2_INIT@l
210         sync
211         mtspr   l2cr, r3        
212 #ifdef CONFIG_ALTIVEC
213         dssall
214 #endif
215         /* invalidate the L2 cache */
216         bl      l2cache_invalidate
217         sync
218 #endif
219         
220         /*
221          * Calculate absolute address in FLASH and jump there
222          *------------------------------------------------------*/
223         lis     r3, CFG_MONITOR_BASE@h
224         ori     r3, r3, CFG_MONITOR_BASE@l
225         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
226         mtlr    r3
227         blr
228
229 in_flash:
230         /* let the C-code set up the rest                       */
231         /*                                                      */
232         /* Be careful to keep code relocatable !                */
233         /*------------------------------------------------------*/
234         /* perform low-level init */
235
236         /* enable extended addressing */
237         bl      enable_ext_addr
238         
239         /* setup the bats */
240         bl      setup_bats
241         sync
242
243 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
244         /* setup ccsrbar */
245         bl      setup_ccsrbar
246 #endif
247         
248         /* setup the law entries */
249         bl      law_entry
250         sync
251
252         /* Don't use this feature due to bug in 8641D PD4 */
253         /* Disable ERD_DIS */
254         lis     r3, CFG_CCSRBAR@h
255         ori     r3, r3, 0x1008
256         lwz     r4, 0(r3)
257         oris    r4, r4, 0x4000
258         stw     r4, 0(r3)
259         sync
260
261 #if (EMULATOR_RUN == 1)
262         /* On the emulator we want to adjust these ASAP */
263         /* otherwise things are sloooow */
264         /* Setup OR0 (LALE FIX)*/
265         lis     r3, CFG_CCSRBAR@h
266         ori     r3, r3, 0x5004
267         li      r4, 0x0FF3
268         stw     r4, 0(r3)
269         sync
270
271         /* Setup LCRR */
272         lis     r3, CFG_CCSRBAR@h
273         ori     r3, r3, 0x50D4
274         lis     r4, 0x8000
275         ori     r4, r4, 0x0002
276         stw     r4, 0(r3)
277         sync
278 #endif
279 #if 1   
280         /* make sure timer enabled in guts register too */
281         lis     r3, CFG_CCSRBAR@h
282         oris    r3,r3, 0xE
283         ori     r3,r3,0x0070  /*Jason from 3*/
284         lwz     r4, 0(r3)
285         lis     r5,0xFFFC     /*Jason from 0xffff*/
286         ori     r5,r5,0x5FFF
287         and     r4,r4,r5
288         stw     r4,0(r3)
289 #endif  
290         /*
291          * Cache must be enabled here for stack-in-cache trick.
292          * This means we need to enable the BATS.
293          * Cache should be turned on after BATs, since by default
294          * everything is write-through.
295          */
296
297         /* enable address translation */
298         bl      enable_addr_trans
299         sync
300
301         /* enable and invalidate the data cache */
302 /*      bl      l1dcache_enable */
303         bl      dcache_enable 
304         sync
305
306 #if 1
307         bl      icache_enable
308 #endif
309         
310 #ifdef CFG_INIT_RAM_LOCK
311         bl      lock_ram_in_cache
312         sync
313 #endif
314
315         /* set up the stack pointer in our newly created
316          * cache-ram (r1) */
317         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
318         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
319
320         li      r0, 0           /* Make room for stack frame header and */
321         stwu    r0, -4(r1)      /* clear final stack frame so that      */
322         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
323
324         GET_GOT                 /* initialize GOT access        */
325
326         /* run low-level CPU init code     (from Flash) */
327         bl      cpu_init_f
328         sync
329
330 #ifdef  RUN_DIAG        
331
332         /* Sri:  Code to run the diagnostic automatically */
333
334         /* Load PX_AUX register address in r4 */
335         lis     r4, 0xf810
336         ori     r4, r4, 0x6
337         /* Load contents of PX_AUX in r3 bits 24 to 31*/
338         lbz     r3, 0(r4)
339
340         /* Mask and obtain the bit in r3 */
341         rlwinm. r3, r3, 0, 24, 24
342         /* If not zero, jump and continue with u-boot */
343         bne     diag_done
344
345         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
346         lbz     r3, 0(r4)
347         /* Set the MSB of the register value */
348         ori     r3, r3, 0x80
349         /* Write value in r3 back to PX_AUX */
350         stb     r3, 0(r4)
351
352         /* Get the address to jump to in r3*/
353         lis     r3, CFG_DIAG_ADDR@h
354         ori     r3, r3, CFG_DIAG_ADDR@l
355
356         /* Load the LR with the branch address */
357         mtlr    r3
358
359         /* Branch to diagnostic */
360         blr
361         
362 diag_done:      
363 #endif        
364
365   /*      bl      l2cache_enable*/
366         mr      r3, r21
367
368         /* r3: BOOTFLAG */
369         /* run 1st part of board init code (from Flash)   */
370         bl      board_init_f
371         sync
372
373         /* NOTREACHED */
374
375         .globl  invalidate_bats
376 invalidate_bats:
377         
378         /* invalidate BATs */
379         mtspr   IBAT0U, r0
380         mtspr   IBAT1U, r0
381         mtspr   IBAT2U, r0
382         mtspr   IBAT3U, r0
383         mtspr   IBAT4U, r0
384         mtspr   IBAT5U, r0
385         mtspr   IBAT6U, r0
386         mtspr   IBAT7U, r0
387
388         isync
389         mtspr   DBAT0U, r0
390         mtspr   DBAT1U, r0
391         mtspr   DBAT2U, r0
392         mtspr   DBAT3U, r0
393         mtspr   DBAT4U, r0
394         mtspr   DBAT5U, r0
395         mtspr   DBAT6U, r0
396         mtspr   DBAT7U, r0
397
398         isync
399         sync
400         blr
401         
402         
403         /* setup_bats - set them up to some initial state */
404         .globl  setup_bats
405 setup_bats:
406         
407         addis   r0, r0, 0x0000
408
409         /* IBAT 0 */
410         addis   r4, r0, CFG_IBAT0L@h
411         ori     r4, r4, CFG_IBAT0L@l
412         addis   r3, r0, CFG_IBAT0U@h
413         ori     r3, r3, CFG_IBAT0U@l
414         mtspr   IBAT0L, r4
415         mtspr   IBAT0U, r3
416         isync
417
418         /* DBAT 0 */
419         addis   r4, r0, CFG_DBAT0L@h
420         ori     r4, r4, CFG_DBAT0L@l
421         addis   r3, r0, CFG_DBAT0U@h
422         ori     r3, r3, CFG_DBAT0U@l
423         mtspr   DBAT0L, r4
424         mtspr   DBAT0U, r3
425         isync
426
427         /* IBAT 1 */
428         addis   r4, r0, CFG_IBAT1L@h
429         ori     r4, r4, CFG_IBAT1L@l
430         addis   r3, r0, CFG_IBAT1U@h
431         ori     r3, r3, CFG_IBAT1U@l
432         mtspr   IBAT1L, r4
433         mtspr   IBAT1U, r3
434         isync
435
436         /* DBAT 1 */
437         addis   r4, r0, CFG_DBAT1L@h
438         ori     r4, r4, CFG_DBAT1L@l
439         addis   r3, r0, CFG_DBAT1U@h
440         ori     r3, r3, CFG_DBAT1U@l
441         mtspr   DBAT1L, r4
442         mtspr   DBAT1U, r3
443         isync
444
445         /* IBAT 2 */
446         addis   r4, r0, CFG_IBAT2L@h
447         ori     r4, r4, CFG_IBAT2L@l
448         addis   r3, r0, CFG_IBAT2U@h
449         ori     r3, r3, CFG_IBAT2U@l
450         mtspr   IBAT2L, r4
451         mtspr   IBAT2U, r3
452         isync
453
454         /* DBAT 2 */
455         addis   r4, r0, CFG_DBAT2L@h
456         ori     r4, r4, CFG_DBAT2L@l
457         addis   r3, r0, CFG_DBAT2U@h
458         ori     r3, r3, CFG_DBAT2U@l
459         mtspr   DBAT2L, r4
460         mtspr   DBAT2U, r3
461         isync
462
463         /* IBAT 3 */
464         addis   r4, r0, CFG_IBAT3L@h
465         ori     r4, r4, CFG_IBAT3L@l
466         addis   r3, r0, CFG_IBAT3U@h
467         ori     r3, r3, CFG_IBAT3U@l
468         mtspr   IBAT3L, r4
469         mtspr   IBAT3U, r3
470         isync
471
472         /* DBAT 3 */
473         addis   r4, r0, CFG_DBAT3L@h
474         ori     r4, r4, CFG_DBAT3L@l
475         addis   r3, r0, CFG_DBAT3U@h
476         ori     r3, r3, CFG_DBAT3U@l
477         mtspr   DBAT3L, r4
478         mtspr   DBAT3U, r3
479         isync
480
481         /* IBAT 4 */
482         addis   r4, r0, CFG_IBAT4L@h
483         ori     r4, r4, CFG_IBAT4L@l
484         addis   r3, r0, CFG_IBAT4U@h
485         ori     r3, r3, CFG_IBAT4U@l
486         mtspr   IBAT4L, r4
487         mtspr   IBAT4U, r3
488         isync
489
490         /* DBAT 4 */
491         addis   r4, r0, CFG_DBAT4L@h
492         ori     r4, r4, CFG_DBAT4L@l
493         addis   r3, r0, CFG_DBAT4U@h
494         ori     r3, r3, CFG_DBAT4U@l
495         mtspr   DBAT4L, r4
496         mtspr   DBAT4U, r3
497         isync
498
499         /* IBAT 5 */
500         addis   r4, r0, CFG_IBAT5L@h
501         ori     r4, r4, CFG_IBAT5L@l
502         addis   r3, r0, CFG_IBAT5U@h
503         ori     r3, r3, CFG_IBAT5U@l
504         mtspr   IBAT5L, r4
505         mtspr   IBAT5U, r3
506         isync
507
508         /* DBAT 5 */
509         addis   r4, r0, CFG_DBAT5L@h
510         ori     r4, r4, CFG_DBAT5L@l
511         addis   r3, r0, CFG_DBAT5U@h
512         ori     r3, r3, CFG_DBAT5U@l
513         mtspr   DBAT5L, r4
514         mtspr   DBAT5U, r3
515         isync
516
517         /* IBAT 6 */
518         addis   r4, r0, CFG_IBAT6L@h
519         ori     r4, r4, CFG_IBAT6L@l
520         addis   r3, r0, CFG_IBAT6U@h
521         ori     r3, r3, CFG_IBAT6U@l
522         mtspr   IBAT6L, r4
523         mtspr   IBAT6U, r3
524         isync
525
526         /* DBAT 6 */
527         addis   r4, r0, CFG_DBAT6L@h
528         ori     r4, r4, CFG_DBAT6L@l
529         addis   r3, r0, CFG_DBAT6U@h
530         ori     r3, r3, CFG_DBAT6U@l
531         mtspr   DBAT6L, r4
532         mtspr   DBAT6U, r3
533         isync
534
535         /* IBAT 7 */
536         addis   r4, r0, CFG_IBAT7L@h
537         ori     r4, r4, CFG_IBAT7L@l
538         addis   r3, r0, CFG_IBAT7U@h
539         ori     r3, r3, CFG_IBAT7U@l
540         mtspr   IBAT7L, r4
541         mtspr   IBAT7U, r3
542         isync
543
544         /* DBAT 7 */
545         addis   r4, r0, CFG_DBAT7L@h
546         ori     r4, r4, CFG_DBAT7L@l
547         addis   r3, r0, CFG_DBAT7U@h
548         ori     r3, r3, CFG_DBAT7U@l
549         mtspr   DBAT7L, r4
550         mtspr   DBAT7U, r3
551         isync
552
553 1:      
554         addis   r3, 0, 0x0000
555         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
556         isync
557
558 tlblp:
559         tlbie   r3
560         sync
561         addi    r3, r3, 0x1000
562         cmp     0, 0, r3, r5
563         blt tlblp
564
565         blr
566
567         .globl enable_addr_trans
568 enable_addr_trans:
569         /* enable address translation */
570         mfmsr   r5
571         ori     r5, r5, (MSR_IR | MSR_DR)
572         mtmsr   r5
573         isync
574         blr
575
576         .globl disable_addr_trans
577 disable_addr_trans:
578         /* disable address translation */
579         mflr    r4
580         mfmsr   r3
581         andi.   r0, r3, (MSR_IR | MSR_DR)
582         beqlr
583         andc    r3, r3, r0
584         mtspr   SRR0, r4
585         mtspr   SRR1, r3
586         rfi
587
588 /*
589  * This code finishes saving the registers to the exception frame
590  * and jumps to the appropriate handler for the exception.
591  * Register r21 is pointer into trap frame, r1 has new stack pointer.
592  */
593         .globl  transfer_to_handler
594 transfer_to_handler:
595         stw     r22,_NIP(r21)
596         lis     r22,MSR_POW@h
597         andc    r23,r23,r22
598         stw     r23,_MSR(r21)
599         SAVE_GPR(7, r21)
600         SAVE_4GPRS(8, r21)
601         SAVE_8GPRS(12, r21)
602         SAVE_8GPRS(24, r21)
603         mflr    r23
604         andi.   r24,r23,0x3f00          /* get vector offset */
605         stw     r24,TRAP(r21)
606         li      r22,0
607         stw     r22,RESULT(r21)
608         mtspr   SPRG2,r22               /* r1 is now kernel sp */
609         lwz     r24,0(r23)              /* virtual address of handler */
610         lwz     r23,4(r23)              /* where to go when done */
611         mtspr   SRR0,r24
612         mtspr   SRR1,r20
613         mtlr    r23
614         SYNC
615         rfi                             /* jump to handler, enable MMU */
616
617 int_return:
618         mfmsr   r28             /* Disable interrupts */
619         li      r4,0
620         ori     r4,r4,MSR_EE
621         andc    r28,r28,r4
622         SYNC                    /* Some chip revs need this... */
623         mtmsr   r28
624         SYNC
625         lwz     r2,_CTR(r1)
626         lwz     r0,_LINK(r1)
627         mtctr   r2
628         mtlr    r0
629         lwz     r2,_XER(r1)
630         lwz     r0,_CCR(r1)
631         mtspr   XER,r2
632         mtcrf   0xFF,r0
633         REST_10GPRS(3, r1)
634         REST_10GPRS(13, r1)
635         REST_8GPRS(23, r1)
636         REST_GPR(31, r1)
637         lwz     r2,_NIP(r1)     /* Restore environment */
638         lwz     r0,_MSR(r1)
639         mtspr   SRR0,r2
640         mtspr   SRR1,r0
641         lwz     r0,GPR0(r1)
642         lwz     r2,GPR2(r1)
643         lwz     r1,GPR1(r1)
644         SYNC
645         rfi
646
647         .globl  dc_read
648 dc_read:
649         blr
650
651         .globl get_pvr
652 get_pvr:
653         mfspr   r3, PVR
654         blr
655
656         .globl get_svr
657 get_svr:
658         mfspr   r3, SVR
659         blr
660
661
662 /*------------------------------------------------------------------------------- */
663 /* Function:     in8 */
664 /* Description:  Input 8 bits */
665 /*------------------------------------------------------------------------------- */
666         .globl  in8
667 in8:
668         lbz     r3,0x0000(r3)
669         blr
670
671 /*------------------------------------------------------------------------------- */
672 /* Function:     out8 */
673 /* Description:  Output 8 bits */
674 /*------------------------------------------------------------------------------- */
675         .globl  out8
676 out8:
677         stb     r4,0x0000(r3)
678         blr
679
680 /*------------------------------------------------------------------------------- */
681 /* Function:     out16 */
682 /* Description:  Output 16 bits */
683 /*------------------------------------------------------------------------------- */
684         .globl  out16
685 out16:
686         sth     r4,0x0000(r3)
687         blr
688
689 /*------------------------------------------------------------------------------- */
690 /* Function:     out16r */
691 /* Description:  Byte reverse and output 16 bits */
692 /*------------------------------------------------------------------------------- */
693         .globl  out16r
694 out16r:
695         sthbrx  r4,r0,r3
696         blr
697
698 /*------------------------------------------------------------------------------- */
699 /* Function:     out32 */
700 /* Description:  Output 32 bits */
701 /*------------------------------------------------------------------------------- */
702         .globl  out32
703 out32:
704         stw     r4,0x0000(r3)
705         blr
706
707 /*------------------------------------------------------------------------------- */
708 /* Function:     out32r */
709 /* Description:  Byte reverse and output 32 bits */
710 /*------------------------------------------------------------------------------- */
711         .globl  out32r
712 out32r:
713         stwbrx  r4,r0,r3
714         blr
715
716 /*------------------------------------------------------------------------------- */
717 /* Function:     in16 */
718 /* Description:  Input 16 bits */
719 /*------------------------------------------------------------------------------- */
720         .globl  in16
721 in16:
722         lhz     r3,0x0000(r3)
723         blr
724
725 /*------------------------------------------------------------------------------- */
726 /* Function:     in16r */
727 /* Description:  Input 16 bits and byte reverse */
728 /*------------------------------------------------------------------------------- */
729         .globl  in16r
730 in16r:
731         lhbrx   r3,r0,r3
732         blr
733
734 /*------------------------------------------------------------------------------- */
735 /* Function:     in32 */
736 /* Description:  Input 32 bits */
737 /*------------------------------------------------------------------------------- */
738         .globl  in32
739 in32:
740         lwz     3,0x0000(3)
741         blr
742
743 /*------------------------------------------------------------------------------- */
744 /* Function:     in32r */
745 /* Description:  Input 32 bits and byte reverse */
746 /*------------------------------------------------------------------------------- */
747         .globl  in32r
748 in32r:
749         lwbrx   r3,r0,r3
750         blr
751
752 /*------------------------------------------------------------------------------- */
753 /* Function:     ppcDcbf */
754 /* Description:  Data Cache block flush */
755 /* Input:        r3 = effective address */
756 /* Output:       none. */
757 /*------------------------------------------------------------------------------- */
758         .globl  ppcDcbf
759 ppcDcbf:
760         dcbf    r0,r3
761         blr
762
763 /*------------------------------------------------------------------------------- */
764 /* Function:     ppcDcbi */
765 /* Description:  Data Cache block Invalidate */
766 /* Input:        r3 = effective address */
767 /* Output:       none. */
768 /*------------------------------------------------------------------------------- */
769         .globl  ppcDcbi
770 ppcDcbi:
771         dcbi    r0,r3
772         blr
773
774 /*--------------------------------------------------------------------------
775  * Function:     ppcDcbz
776  * Description:  Data Cache block zero.
777  * Input:        r3 = effective address
778  * Output:       none.
779  *-------------------------------------------------------------------------- */
780
781         .globl  ppcDcbz
782 ppcDcbz:
783         dcbz    r0,r3
784         blr
785
786 /*-------------------------------------------------------------------------- */
787 /* Function:     ppcSync */
788 /* Description:  Processor Synchronize */
789 /* Input:        none. */
790 /* Output:       none. */
791 /*-------------------------------------------------------------------------- */
792         .globl  ppcSync
793 ppcSync:
794         sync
795         blr
796         
797 /*-----------------------------------------------------------------------*/
798 /*
799  * void relocate_code (addr_sp, gd, addr_moni)
800  *
801  * This "function" does not return, instead it continues in RAM
802  * after relocating the monitor code.
803  *
804  * r3 = dest
805  * r4 = src
806  * r5 = length in bytes
807  * r6 = cachelinesize
808  */
809         .globl  relocate_code
810 relocate_code:
811
812         mr      r1,  r3         /* Set new stack pointer                */
813         mr      r9,  r4         /* Save copy of Global Data pointer     */
814         mr      r10, r5         /* Save copy of Destination Address     */
815         
816         mr      r3,  r5                         /* Destination Address  */
817         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
818         ori     r4, r4, CFG_MONITOR_BASE@l
819         lwz     r5, GOT(__init_end)
820         sub     r5, r5, r4
821         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
822
823         /*
824          * Fix GOT pointer:
825          *
826          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
827          *
828          * Offset:
829          */
830         sub     r15, r10, r4
831
832         /* First our own GOT */
833         add     r14, r14, r15
834         /* then the one used by the C code */
835         add     r30, r30, r15
836
837         /*
838          * Now relocate code
839          */
840 #ifdef CONFIG_ECC
841         bl      board_relocate_rom
842         sync
843         mr      r3, r10                         /* Destination Address  */
844         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
845         ori     r4, r4, CFG_MONITOR_BASE@l
846         lwz     r5, GOT(__init_end)
847         sub     r5, r5, r4
848         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
849 #else
850         cmplw   cr1,r3,r4
851         addi    r0,r5,3
852         srwi.   r0,r0,2
853         beq     cr1,4f          /* In place copy is not necessary       */
854         beq     7f              /* Protect against 0 count              */
855         mtctr   r0
856         bge     cr1,2f
857
858         la      r8,-4(r4)
859         la      r7,-4(r3)
860 1:      lwzu    r0,4(r8)
861         stwu    r0,4(r7)
862         bdnz    1b
863         b       4f
864
865 2:      slwi    r0,r0,2
866         add     r8,r4,r0
867         add     r7,r3,r0
868 3:      lwzu    r0,-4(r8)
869         stwu    r0,-4(r7)
870         bdnz    3b
871 #endif
872 /*
873  * Now flush the cache: note that we must start from a cache aligned
874  * address. Otherwise we might miss one cache line.
875  */
876 4:      cmpwi   r6,0
877         add     r5,r3,r5
878         beq     7f              /* Always flush prefetch queue in any case */
879         subi    r0,r6,1
880         andc    r3,r3,r0
881         mr      r4,r3
882 5:      dcbst   0,r4
883         add     r4,r4,r6
884         cmplw   r4,r5
885         blt     5b
886         sync                    /* Wait for all dcbst to complete on bus */
887         mr      r4,r3
888 6:      icbi    0,r4
889         add     r4,r4,r6
890         cmplw   r4,r5
891         blt     6b
892 7:      sync                    /* Wait for all icbi to complete on bus */
893         isync
894
895 /*
896  * We are done. Do not return, instead branch to second part of board
897  * initialization, now running from RAM.
898  */
899         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
900         mtlr    r0
901         blr
902
903 in_ram:
904 #ifdef CONFIG_ECC
905         bl      board_init_ecc
906 #endif
907         /*
908          * Relocation Function, r14 point to got2+0x8000
909          *
910          * Adjust got2 pointers, no need to check for 0, this code
911          * already puts a few entries in the table.
912          */
913         li      r0,__got2_entries@sectoff@l
914         la      r3,GOT(_GOT2_TABLE_)
915         lwz     r11,GOT(_GOT2_TABLE_)
916         mtctr   r0
917         sub     r11,r3,r11
918         addi    r3,r3,-4
919 1:      lwzu    r0,4(r3)
920         add     r0,r0,r11
921         stw     r0,0(r3)
922         bdnz    1b
923
924         /*
925          * Now adjust the fixups and the pointers to the fixups
926          * in case we need to move ourselves again.
927          */
928 2:      li      r0,__fixup_entries@sectoff@l
929         lwz     r3,GOT(_FIXUP_TABLE_)
930         cmpwi   r0,0
931         mtctr   r0
932         addi    r3,r3,-4
933         beq     4f
934 3:      lwzu    r4,4(r3)
935         lwzux   r0,r4,r11
936         add     r0,r0,r11
937         stw     r10,0(r3)
938         stw     r0,0(r4)
939         bdnz    3b
940 4:
941 /* clear_bss: */
942         /*
943          * Now clear BSS segment
944          */
945         lwz     r3,GOT(__bss_start)
946         lwz     r4,GOT(_end)
947
948         cmplw   0, r3, r4
949         beq     6f
950
951         li      r0, 0
952 5:
953         stw     r0, 0(r3)
954         addi    r3, r3, 4
955         cmplw   0, r3, r4
956         bne     5b
957 6:
958         mr      r3, r9          /* Init Date pointer            */
959         mr      r4, r10         /* Destination Address          */
960         bl      board_init_r
961
962         /* not reached - end relocate_code */
963 /*-----------------------------------------------------------------------*/
964
965         /*
966          * Copy exception vector code to low memory
967          *
968          * r3: dest_addr
969          * r7: source address, r8: end address, r9: target address
970          */
971         .globl  trap_init
972 trap_init:
973         lwz     r7, GOT(_start)
974         lwz     r8, GOT(_end_of_vectors)
975
976         li      r9, 0x100               /* reset vector always at 0x100 */
977
978         cmplw   0, r7, r8
979         bgelr                           /* return if r7>=r8 - just in case */
980
981         mflr    r4                      /* save link register           */
982 1:
983         lwz     r0, 0(r7)
984         stw     r0, 0(r9)
985         addi    r7, r7, 4
986         addi    r9, r9, 4
987         cmplw   0, r7, r8
988         bne     1b
989
990         /*
991          * relocate `hdlr' and `int_return' entries
992          */
993         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
994         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
995 2:
996         bl      trap_reloc
997         addi    r7, r7, 0x100           /* next exception vector        */
998         cmplw   0, r7, r8
999         blt     2b
1000
1001         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1002         bl      trap_reloc
1003
1004         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1005         bl      trap_reloc
1006
1007         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1008         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1009 3:
1010         bl      trap_reloc
1011         addi    r7, r7, 0x100           /* next exception vector        */
1012         cmplw   0, r7, r8
1013         blt     3b
1014
1015         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1016         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1017 4:
1018         bl      trap_reloc
1019         addi    r7, r7, 0x100           /* next exception vector        */
1020         cmplw   0, r7, r8
1021         blt     4b
1022
1023         /* enable execptions from RAM vectors */
1024         mfmsr   r7
1025         li      r8,MSR_IP
1026         andc    r7,r7,r8
1027         mtmsr   r7
1028
1029         mtlr    r4                      /* restore link register        */
1030         blr
1031
1032         /*
1033          * Function: relocate entries for one exception vector
1034          */
1035 trap_reloc:
1036         lwz     r0, 0(r7)               /* hdlr ...                     */
1037         add     r0, r0, r3              /*  ... += dest_addr            */
1038         stw     r0, 0(r7)
1039
1040         lwz     r0, 4(r7)               /* int_return ...               */
1041         add     r0, r0, r3              /*  ... += dest_addr            */
1042         stw     r0, 4(r7)
1043
1044         sync
1045         isync
1046
1047         blr
1048
1049 .globl enable_ext_addr
1050 enable_ext_addr:
1051         mfspr   r0, HID0
1052         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1053         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1054         mtspr   HID0, r0
1055         sync
1056         isync
1057         blr
1058
1059 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1060 .globl setup_ccsrbar
1061 setup_ccsrbar:          
1062         /* Special sequence needed to update CCSRBAR itself */
1063         lis     r4, CFG_CCSRBAR_DEFAULT@h
1064         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
1065
1066         lis     r5, CFG_CCSRBAR@h
1067         ori     r5, r5, CFG_CCSRBAR@l
1068         srwi    r6,r5,12
1069         stw     r6, 0(r4)
1070         isync
1071
1072         lis     r5, 0xffff
1073         ori     r5,r5,0xf000
1074         lwz     r5, 0(r5)
1075         isync
1076
1077         lis     r3, CFG_CCSRBAR@h
1078         lwz     r5, CFG_CCSRBAR@l(r3)
1079         isync
1080         
1081         blr
1082 #endif
1083                         
1084 #ifdef CFG_INIT_RAM_LOCK
1085 lock_ram_in_cache:
1086         /* Allocate Initial RAM in data cache.
1087          */
1088         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1089         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1090         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1091                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1092         mtctr   r2
1093 1:
1094         dcbz    r0, r3
1095         addi    r3, r3, 32
1096         bdnz    1b
1097 #if 1
1098 /* Lock the data cache */
1099         mfspr   r0, HID0
1100         ori     r0, r0, 0x1000
1101         sync
1102         mtspr   HID0, r0
1103         sync
1104         blr
1105 #endif
1106 #if 0
1107         /* Lock the first way of the data cache */
1108         mfspr   r0, LDSTCR
1109         ori     r0, r0, 0x0080
1110 #if defined(CONFIG_ALTIVEC)
1111         dssall
1112 #endif
1113         sync
1114         mtspr   LDSTCR, r0
1115         sync
1116         isync
1117         blr
1118 #endif
1119         
1120 .globl unlock_ram_in_cache
1121 unlock_ram_in_cache:
1122         /* invalidate the INIT_RAM section */
1123         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1124         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1125         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1126                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1127         mtctr   r2
1128 1:      icbi    r0, r3
1129         addi    r3, r3, 32
1130         bdnz    1b
1131         sync                    /* Wait for all icbi to complete on bus */
1132         isync
1133 #if 1
1134 /* Unlock the data cache and invalidate it */
1135         mfspr   r0, HID0
1136         li      r3,0x1000
1137         andc    r0,r0,r3
1138         li      r3,0x0400
1139         or      r0,r0,r3
1140         sync
1141         mtspr   HID0, r0
1142         sync
1143         blr
1144 #endif
1145 #if 0   
1146         /* Unlock the first way of the data cache */
1147         mfspr   r0, LDSTCR
1148         li      r3,0x0080
1149         andc    r0,r0,r3
1150 #ifdef CONFIG_ALTIVEC
1151         dssall
1152 #endif
1153         sync
1154         mtspr   LDSTCR, r0
1155         sync
1156         isync
1157         li      r3,0x0400
1158         or      r0,r0,r3
1159         sync
1160         mtspr   HID0, r0
1161         sync
1162         blr
1163 #endif
1164 #endif
1165
1166 /* If this is a multi-cpu system then we need to handle the
1167  * 2nd cpu.  The assumption is that the 2nd cpu is being
1168  * held in boot holdoff mode until the 1st cpu unlocks it
1169  * from Linux.  We'll do some basic cpu init and then pass
1170  * it to the Linux Reset Vector.
1171  * Sri:  Much of this initialization is not required. Linux
1172  * rewrites the bats, and the sprs and also enables the L1 cache.      
1173  */
1174 #if (CONFIG_NUM_CPUS > 1)
1175 .globl secondary_cpu_setup
1176 secondary_cpu_setup:    
1177         /* Do only core setup on all cores except cpu0 */
1178         bl      invalidate_bats
1179         sync
1180         bl      enable_ext_addr
1181         
1182 #ifdef CFG_L2
1183         /* init the L2 cache */
1184         addis   r3, r0, L2_INIT@h
1185         ori     r3, r3, L2_INIT@l
1186         sync
1187         mtspr   l2cr, r3
1188 #ifdef CONFIG_ALTIVEC
1189         dssall
1190 #endif
1191         /* invalidate the L2 cache */
1192         bl      l2cache_invalidate
1193         sync
1194 #endif
1195
1196         /* setup the bats */
1197         bl      setup_bats
1198         sync
1199         /* enable address translation */
1200         bl      enable_addr_trans
1201         sync
1202
1203         /* enable and invalidate the data cache */
1204         bl      dcache_enable
1205         sync
1206
1207         /* enable and invalidate the instruction cache*/
1208         bl      icache_enable
1209         sync
1210         
1211         /* Set up MSR and HID0, HID1*/        
1212         /* Enable interrupts */
1213 /*        mfmsr r28     
1214          li     r4,0
1215         ori     r4,r4,MSR_EE
1216         or      r28,r28,r4
1217         mtmsr   r28
1218   */      
1219
1220         /* TBEN  in HID0 */
1221         mfspr   r4, HID0
1222         oris    r4, r4, 0x0400 
1223         mtspr   HID0, r4
1224         sync
1225         isync
1226         
1227         /*SYNCBE|ABE in HID1*/
1228         mfspr   r4, HID1
1229         ori     r4, r4, 0x0C00 
1230         mtspr   HID1, r4
1231         sync
1232         isync
1233         
1234         lis     r3, CONFIG_LINUX_RESET_VEC@h
1235         ori     r3, r3, CONFIG_LINUX_RESET_VEC@l
1236         mtlr    r3
1237         blr
1238         
1239         /* Never Returns, Running in Linux Now */    
1240 #endif
1241