RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / cpu / bcmcore / src / bcmcore_cpuinit.S
blob606589365e9a743b004fa7ef409ecad2e9e4d23e
1 /*  *********************************************************************
2     *  SB1250 Board Support Package
3     *  
4     *  CPU initialization                       File: bcmcore_cpuinit.S
5     *  
6     *  This module contains code to initialize the CPU cores.
7     *  
8     *  Note: all the routines in this module rely on registers only,
9     *        since DRAM may not be active yet.
10     *
11     *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
12     *  
13     *********************************************************************  
14     *
15     *  XX Copyright 2000,2001
16     *  Broadcom Corporation. All rights reserved.
17     *
18     *  BROADCOM PROPRIETARY AND CONFIDENTIAL
19     *  
20     *  This software is furnished under license and may be used and 
21     *  copied only in accordance with the license.
22     ********************************************************************* */
24 #include "sbmips.h"
25 #include "exception.h"
26 #include "bsp_config.h"
27 #include "mipsmacros.h"
28 #include "cpu_config.h"                 /* for ERET and HAZARD */
29 #include "cfe_iocb.h"
32                 .text
34                 .set mips32
36 /*  *********************************************************************
37     *  Macros
38     ********************************************************************* */
40 #define R_CPU_CP0INIT _TBLIDX(0)
41 #define R_CPU_L1CINIT _TBLIDX(1)
42 #define R_CPU_SETLEDS _TBLIDX(2)
44 #define SETLEDS1(a,b,c,d)                     \
45        li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
46        CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
47 #define SETLEDS(a,b,c,d)                     \
48        li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
49        CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
51 cpuinit_table:
52                 _LONG_  bcmcore_cp0_init        # [ 0 ] R_CPU_CP0INIT
53                 _LONG_  bcmcore_l1cache_init    # [ 1 ] R_CPU_L1CINIT
54                 _LONG_  board_setleds           # [ 2 ] R_CPU_SETLEDS
57 /*  *********************************************************************
58     *  BCMCORE_CP0_INIT()
59     *  
60     *  Initialize an BCMCORE CPU's CP0 registers
61     *  
62     *  Input parameters: 
63     *      nothing
64     *      
65     *  Return value:
66     *      nothing
67     *  
68     *  Registers used:
69     *      all
70     ********************************************************************* */
72         
73 LEAF(bcmcore_cp0_init)
75                 .set    noreorder
77                 mtc0    zero,C0_WATCHLO         # Watch registers.
78                 mtc0    zero,C0_WATCHHI
79                 mtc0    zero,C0_CAUSE           # must clear before writing SR
81                 mfc0    v0,C0_SR                # Get status register
82                 and     v0,M_SR_SR              # preserve soft reset
83 #ifdef DEBUG_ENV_ICE
84                 and     v0,~M_SR_BEV
85 #else
86                 or      v0,M_SR_BEV             # exceptions to boot vector
87 #endif
88                 mtc0    v0,C0_SR                # set up the status register
90                 mfc0    v0,C0_PRID
91                 and     v0,0x00ffff00
92                 bne     v0,0x00029000,1f        # Broadcom BCM330X
93                 nop
94                 mfc0    v0,C0_DIAGNOSTIC
95                 or      v0,0x80000000           # Enable icache
96                 or      v0,0x40000000           # Enable dcache
97                 mtc0    v0,C0_DIAGNOSTIC
98         
99 1:              bne     v0,0x00019700,2f        # 74k core
100                 mfc0    v0,C0_CONFIG,7
101                 or      v0,(1 << 29)
102                 mtc0    v0,C0_CONFIG,7
104 2:              mtc0    zero,C0_COUNT
106         #
107         # This is probably not the right init value for C0_COMPARE,
108         # but it seems to be necessary for the sim model right now.
109         #
111                 li      v0,-1
112                 mtc0    v0,C0_COMPARE
113                 nop
115         #
116         # Initialize all the TLB entries to some invalid value
117         #
119                 mtc0    zero,C0_TLBHI           # TLB entry (high half)
120                 nop
122                 mtc0    zero,C0_TLBLO0          /* tlblo0 = invalid */
123                 nop
124                 mtc0    zero,C0_TLBLO1          /* tlblo1 = invalid */
125                 nop
126                 mtc0    zero,C0_PGMASK          /* 4K pages */
127                 nop
129                 li      t0,K1BASE               /* tlbhi  = impossible vpn */
130                 mfc0    v0,C0_CONFIG,1
131                 li      t1,M_CFG_MMUSIZE
132                 and     t1,v0
133                 srl     t1,S_CFG_MMUSIZE        /* index */
134         
136                 nop
137 1:              mtc0    t0,C0_TLBHI
138                 nop
139                 mtc0    t1,C0_INX
140                 nop
141                 addu    t0,0x2000               /* inc vpn */
142                 tlbwi
143                 bnez    t1,1b
144                 subu    t1,1                    # BDSLOT
145                 .set reorder
149                 jr      ra
152 END(bcmcore_cp0_init)
155 /*  *********************************************************************
156     *  BCMCORE_CPUINIT
157     *  
158     *  Do initialization of the Broadcom core
159     *  
160     *  Input parameters: 
161     *      nothing
162     *      
163     *  Return value:
164     *      nothing
165     ********************************************************************* */
168 LEAF(bcmcore_cpuinit)
170                 move    fp,ra
172                 SETLEDS1('C','P','U','I')
173                 CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
174 #if  CFG_INIT_L1 > 0
175                 SETLEDS1('L','1','C','I')
176                 CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
177 #endif 
178                 move    ra,fp
179                 j       ra
181 END(bcmcore_cpuinit)
184 /*  *********************************************************************
185     *  BCMCORE_NULL
186     *  
187     *  Dummy handler for routines we don't need to implement, like
188     *  the multiprocessor stuff
189     *  
190     *  Input parameters: 
191     *      nothing
192     *      
193     *  Return value:
194     *      nothing
195     *      
196     *  Registers used:
197     *      none
198     ********************************************************************* */
200 LEAF(bcmcore_null)
202                 j       ra
204 END(bcmcore_null)
207 /*  *********************************************************************
208     *  BCMCORE_CPURESTART
209     *  
210     *  This routine is called when someone soft-exits to CFE.  We
211     *  reinitialize any CP0 stuff here.
212     *  
213     *  Input parameters: 
214     *      nothing
215     *      
216     *  Return value:
217     *      nothing
218     ********************************************************************* */
220 LEAF(bcmcore_cpurestart)
222                 j       ra
224 END(bcmcore_cpurestart)
227 /*  *********************************************************************
228     *  BCMCORE_CACHEOPS
229     *  
230     *  Perform various cache operations on a BCM Core
231     *  
232     *  Input parameters: 
233     *      a0 - flag bits (CFE_CACHE_xxx)
234     *      
235     *  Return value:
236     *      nothing
237     *      
238     *  Registers used:
239     *      t0,t1,t2,t3,v1,s0
240     ********************************************************************* */
242 LEAF(bcmcore_cacheops)
244                 move    s0,ra
246                 move    v1,a0
248         /*
249          * With no flags, we flush L1D and invalid L1I
250          */
252                 bne     v1,zero,1f
253                 li      v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
256         /*
257          * Flush the D-Cache, since the program we loaded is "data".
258          */
260                 and     a0,v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_D | CFE_CACHE_FLUSH_RANGE | CFE_CACHE_INVAL_RANGE
261                 beq     a0,zero,1f
262                 jal     bcmcore_l1cache_flush_d
265         /*
266          * Invalidate the I-Cache, so that addresses in the program
267          * region will miss and need to be filled from the data we 
268          * just flushed above.
269          */
271                 and     a0,v1,CFE_CACHE_INVAL_I
272                 beq     a0,zero,1f
273                 jal     bcmcore_l1cache_inval_i
276                 move    ra,s0
277                 j       ra
279 END(bcmcore_cacheops)
283 /*  *********************************************************************
284     *  BCMCORE_TLBHANDLER
285     *  
286     *  This is the TLB exception handler for the bcmcore
287     *  
288     *  Note: only K0 and K1 are available to us at this time.
289     *  
290     *  Input parameters: 
291     *      nothing
292     *      
293     *  Return value:
294     *      nothing
295     ********************************************************************* */
298 LEAF(bcmcore_tlbhandler)
299                 .set    noreorder
300                 .set    noat
302 #ifdef BCM4704        
303                 nop           
304 #endif                              
308  * This requires a bit of explanation:  We only support 256KB
309  * of mapped space for the boot program.  This space will be 
310  * mapped from 0x2000_0000 to 0x2004_0000 to some physical 
311  * memory allocated by the firmware.  This is 64 pages
312  * of 4KB each.
314  * We know our BadVPN2 will be in the range
315  * 0x100000 to 0x1001F0, since the memory is mapped from
316  * 0x2000_0000 to 0x2004_0000.  BadVPN2 plus the four bits
317  * of zeroes at the end are bits 31..9
318  * 
319  * We also want to place the PTEbase on something other than
320  * a 16MB boundary.  Each entry is 16 bytes, and there
321  * are 64 entries, so we need only 10 bits to address
322  * the entire table (it can therefore be aligned on a
323  * 1KB boundary).
325  * To make this work, we'll shift PTEbase to the right, leaving
326  * the bottom ten bits for the page number, as:
328  *    Bits 31..10: PTEbase
329  *    Bits 9..4:   BadVPN
330  *    Bits 3..0:   16 bytes for table entry
332  * Therefore:
333  *    PTEbase gets shifted right 13 bits.
334  *    BadVPN  gets masked at 6 bits (mask is 0x3F0)
335  *    The bottom 4 bits are zero.
337  * To range check the address, we can shift the Bad VPN
338  * right by 9 bits, and check for values of 0x1000 and
339  * 0x1001.
340  */
343         /*
344          * This part range checks the VPN2 field in the 
345          * context register.  We only handle
346          * VPN2s in the range 0x100000 to 0x1001F0
347          */
348                 mfc0    k0,C0_TLBHI
350                 mfc0    k0,C0_CTEXT             # Get context
351                 sra     k0,8                    # keep hi part
352                 and     k0,0x1FFF               # of VPN2
353                 li      k1,0x1000               # 0x1000 is ok
354                 beq     k0,k1,1f                #
355                 nop                             # BDSLOT
356                 li      k1,0x1001               # 0x1001 is ok
357                 beq     k0,k1,1f                #
358                 nop                             # BDSLOT
360                 li      k0,XTYPE_TLBFILL        # all other bits are not
361                 j       _exc_entry
362                 nop                             # BDSLOT
364 1:              mfc0    k0,C0_CTEXT             # Get context
365                 sra     k0,13                   # Shift PTEbase 
366                 li      k1,0x3FF                # Generate mask to kill 
367                 not     k1                      # BadVPN2 bits
368                 and     k0,k1                   # keep only PTEBase part.
370                 mfc0    k1,C0_CTEXT             # Get Context
371                 and     k1,0x3F0                # Keep only BadVPN2 bits
372                 or      k1,k0                   # Replace PTEBase
374                 ld      k0,0(k1)                # Load entrylo0
375                 ld      k1,8(k1)                # Load entrylo1
376                 mtc0    k0,C0_TLBLO0            # and write to CP0
377                 mtc0    k1,C0_TLBLO1
378                 tlbwr                           # put it in the TLB
379                 ERET
380                 nop
382                 .set    reorder
383                 .set    at
385 END(bcmcore_tlbhandler)
388 /*  *********************************************************************
389     *  End
390     ********************************************************************* */