RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / cfe / cfe / arch / mips / cpu / rm5200 / src / rm5200_cpu.S
blob01c22167220de168b08144be11294991f06df527
1 /*  *********************************************************************
2     *  P5064 Board Support Package
3     *  
4     *  CPU initialization                       File: rm5200_cpuinit.S
5     *  
6     *  This module contains code to initialize the CPU.
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     *  Copyright 2000,2001,2002,2003
16     *  Broadcom Corporation. All rights reserved.
17     *  
18     *  This software is furnished under license and may be used and 
19     *  copied only in accordance with the following terms and 
20     *  conditions.  Subject to these conditions, you may download, 
21     *  copy, install, use, modify and distribute modified or unmodified 
22     *  copies of this software in source and/or binary form.  No title 
23     *  or ownership is transferred hereby.
24     *  
25     *  1) Any source code used, modified or distributed must reproduce 
26     *     and retain this copyright notice and list of conditions 
27     *     as they appear in the source file.
28     *  
29     *  2) No right is granted to use any trade name, trademark, or 
30     *     logo of Broadcom Corporation.  The "Broadcom Corporation" 
31     *     name may not be used to endorse or promote products derived 
32     *     from this software without the prior written permission of 
33     *     Broadcom Corporation.
34     *  
35     *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36     *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37     *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
38     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 
39     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 
40     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41     *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
42     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43     *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44     *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
45     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
46     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 
47     *     THE POSSIBILITY OF SUCH DAMAGE.
48     ********************************************************************* */
50 #include "sbmips.h"
51 #include "bsp_config.h"
52 #include "mipsmacros.h"
53 #include "exception.h"
56                 .text
57                 .set mips64
60 /*  *********************************************************************
61     *  Macros
62     ********************************************************************* */
64 #define CFG_BE          0x00008000      /* Big Endian */
65 #define CFG_EPMASK      0x0f000000      /* Transmit data pattern */
66 #define CFG_EPD         0x00000000      /* D */
67 #define NTLBENTRIES 64
70  * Duplicates from cfe_iocb.h -- warning!
71  */
73 #define CFE_CACHE_FLUSH_D       1
74 #define CFE_CACHE_INVAL_I       2
75 #define CFE_CACHE_INVAL_D       4
76 #define CFE_CACHE_INVAL_L2      8
77 #define CFE_CACHE_FLUSH_L2      16
79 /*  *********************************************************************
80     *  Linkage tables
81     ********************************************************************* */
83 #define R_CPU_CP0INIT   _TBLIDX(0)
84 #define R_CPU_L1CINIT   _TBLIDX(1)
85 #define R_CPU_SETLEDS   _TBLIDX(2)
87 cpuinit_table:
88                 _LONG_  rm5200_cp0_init         # [  0] R_CPU_CP0INIT
89                 _LONG_  rm5200_l1cache_init     # [  1] R_CPU_L1CINIT
90                 _LONG_  board_setleds           # [  2] R_CPU_SETLEDS
92 #define SETLEDS1(a,b,c,d)                     \
93        li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
94        CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
95 #define SETLEDS(a,b,c,d)                     \
96        li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
97        CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
101 /*  *********************************************************************
102     *  RM5200_CP0_INIT
103     *  
104     *  Initialize CP0 registers for an RM5200 core.
105     *  
106     *  Input parameters: 
107     *      nothing
108     *      
109     *  Return value:
110     *      nothing
111     ********************************************************************* */
113 LEAF(rm5200_cp0_init)
115         /*
116          * Set SR and CAUSE to something sensible.
117          */
118                 
119                 .set noreorder
120                 mfc0    t0,C0_PRID
121                 mfc0    v0,C0_SR
122                 mtc0    zero,C0_WATCHLO
123                 mtc0    zero,C0_WATCHHI
124                 li      t1,-1
125                 mtc0    t1,C0_COMPARE
126                 and     v0,M_SR_SR              # preserve Soft Reset
127                 or      v0,M_SR_BEV             # set Boot Exceptions
128                 mtc0    zero,C0_CAUSE           # Must clear WP before
129                 mtc0    v0,C0_SR                # writing STATUS register.
130                 .set reorder
132         
133                 mfc0    t1,C0_CONFIG
135                 mtc0    zero,C0_WATCHLO
136                 mtc0    zero,C0_WATCHHI
138         /* 
139          * make KSEG0 cacheable 
140          */
142                 and     t1,~M_CFG_K0COH
143                 or      t1,V_CFG_K0COH(K_CFG_K0COH_CACHEABLE)
144         
145         /* 
146          * set DDDD rate for CPUs that aren't hardware configured 
147          */
149                 and     t1,~CFG_EPMASK
150                 or      t1,CFG_EPD
152 #ifdef __MIPSEB
153                 or      t1,CFG_BE       
154 #else
155                 and     t1,~CFG_BE      
156 #endif
157                 mtc0    t1,C0_CONFIG
160         /* 
161          * initialize tlb 
162          */
163                 mtc0    zero,C0_TLBLO0          /* tlblo0 = invalid */
164                 mtc0    zero,C0_TLBLO1          /* tlblo1 = invalid */
165                 mtc0    zero,C0_PGMASK
166                 li      t8,K1BASE               /* tlbhi  = impossible vpn */
167                 li      t9,(NTLBENTRIES-1)      /* index */
168                 
170                 .set noreorder
171                 nop
172 1:              mtc0    t8,C0_TLBHI
173                 mtc0    t9,C0_INX
174                 addu    t8,0x2000               /* inc vpn */
175                 tlbwi
176                 bnez    t9,1b
177                 subu    t9,1                    # BDSLOT
178                 .set reorder
180                 j       ra
182 END(rm5200_cp0_init)
185 /*  *********************************************************************
186     *  RM5200_NULL_INIT
187     *  
188     *  This stub routine is used by initialization functions that
189     *  we leave unimplemented.
190     *  
191     *  Input parameters: 
192     *      nothing
193     *      
194     *  Return value:
195     *      nothing
196     ********************************************************************* */
198 LEAF(rm5200_null_init)
199                 j       ra
200 END(rm5200_null_init)
204 /*  *********************************************************************
205     *  RM5200_CPUINIT
206     *  
207     *  Initialize the CPU core.
208     *  
209     *  Input parameters: 
210     *      nothing
211     *      
212     *  Return value:
213     *      nothing
214     ********************************************************************* */
216 LEAF(rm5200_cpuinit)
218                 move    k0,ra                   /* will be trashing RA */
220         /*
221          * Basic CPU initialization
222          */
224                 CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
226         /*
227          * CP0 registers
228          */
231 #------------------------------------------------------------------------------
233         /*
234          * Init the L1 cache.  
235          */
237 #if CFG_INIT_L1
238                 SETLEDS1('L','1','C','I')
239                 CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
240 #endif
242         /*
243          * There is no L2 cache.
244          */
246                 move    ra,k0                   /* saved return address */
247                 j       ra
250 END(rm5200_cpuinit)
252 /*  *********************************************************************
253     *  RM5200_CPURESTART
254     *  
255     *  'Restart' the CPU (reset things back to some sane state after
256     *  a program returns to the firmware)
257     *  
258     *  Input parameters: 
259     *      nothing
260     *      
261     *  Return value:
262     *      nothing
263     ********************************************************************* */
265 LEAF(rm5200_cpurestart)
267                 move    k0,ra
269                 CALLINIT_KSEG0(cpuinit_table,R_CPU_CP0INIT)
271                 LR      v0,cfe_pagetable                # reestablish 
272                 dsll    v0,v0,13                        # see mips_arena.c for this
273                 dmtc0   v0,C0_CTEXT                     # boot area TLBs
275                 move    ra,k0
276                 j       ra
278 END(rm5200_cpurestart)
281 LEAF(rm5200_cacheops)
283                 move    s0,ra
285                 move    v1,a0
287         /*
288          * With no flags, we flush L1D and invalid L1I
289          */
291                 bne     v1,zero,1f
292                 li      v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
295         /*
296          * Flush the D-Cache, since the program we loaded is "data".
297          */
299                 and     a0,v1,CFE_CACHE_FLUSH_D
300                 beq     a0,zero,1f
301                 jal     rm5200_l1cache_flush_d
304         /*
305          * Invalidate the I-Cache, so that addresses in the program
306          * region will miss and need to be filled from the data we 
307          * just flushed above.
308          */
310                 and     a0,v1,CFE_CACHE_INVAL_I
311                 beq     a0,zero,1f
312                 jal     rm5200_l1cache_inval_i
316                 move    ra,s0
317                 j       ra
319 END(rm5200_cacheops)
321 /*  *********************************************************************
322     *  RM5200_TLBHANDLER
323     *  
324     *  This is the TLB exception handler for the RM5200
325     *  
326     *  Note: only K0 and K1 are available to us at this time.
327     *  
328     *  Input parameters: 
329     *      nothing
330     *      
331     *  Return value:
332     *      nothing
333     ********************************************************************* */
336 LEAF(rm5200_tlbhandler)
337                 .set    noreorder
338                 .set    noat
341  * This requires a bit of explanation:  We only support 256KB
342  * of mapped space for the boot program.  This space will be 
343  * mapped from 0x2000_0000 to 0x2004_0000 to some physical 
344  * memory allocated by the firmware.  This is 64 pages
345  * of 4KB each.
347  * We know our BadVPN2 will be in the range
348  * 0x100000 to 0x1001F0, since the memory is mapped from
349  * 0x2000_0000 to 0x2004_0000.  BadVPN2 plus the four bits
350  * of zeroes at the end are bits 31..9
351  * 
352  * We also want to place the PTEbase on something other than
353  * a 16MB boundary.  Each entry is 16 bytes, and there
354  * are 64 entries, so we need only 10 bits to address
355  * the entire table (it can therefore be aligned on a
356  * 1KB boundary).
358  * To make this work, we'll shift PTEbase to the right, leaving
359  * the bottom ten bits for the page number, as:
361  *    Bits 31..10: PTEbase
362  *    Bits 9..4:   BadVPN
363  *    Bits 3..0:   16 bytes for table entry
365  * Therefore:
366  *    PTEbase gets shifted right 13 bits.
367  *    BadVPN  gets masked at 6 bits (mask is 0x3F0)
368  *    The bottom 4 bits are zero.
370  * To range check the address, we can shift the Bad VPN
371  * right by 9 bits, and check for values of 0x1000 and
372  * 0x1001.
373  */
376         /*
377          * This part range checks the VPN2 field in the 
378          * context register.  We only handle
379          * VPN2s in the range 0x100000 to 0x1001F0
380          */
381                 dmfc0   k0,C0_TLBHI
383                 dmfc0   k0,C0_CTEXT             # Get context
384                 dsra    k0,8                    # keep hi part
385                 and     k0,0x1FFF               # of VPN2
386                 li      k1,0x1000               # 0x1000 is ok
387                 beq     k0,k1,1f                #
388                 nop                             # BDSLOT
389                 li      k1,0x1001               # 0x1001 is ok
390                 beq     k0,k1,1f                #
391                 nop                             # BDSLOT
393                 li      k0,XTYPE_TLBFILL        # all other bits are not
394                 j       _exc_entry
395                 nop                             # BDSLOT
397 1:              dmfc0   k0,C0_CTEXT             # Get context
398                 dsra    k0,13                   # Shift PTEbase 
399                 li      k1,0x3FF                # Generate mask to kill 
400                 not     k1                      # BadVPN2 bits
401                 and     k0,k1                   # keep only PTEBase part.
403                 dmfc0   k1,C0_CTEXT             # Get Context
404                 and     k1,0x3F0                # Keep only BadVPN2 bits
405                 or      k1,k0                   # Replace PTEBase
407                 ld      k0,0(k1)                # Load entrylo0
408                 ld      k1,8(k1)                # Load entrylo1
409                 mtc0    k0,C0_TLBLO0            # and write to CP0
410                 mtc0    k1,C0_TLBLO1
411                 tlbwr                           # put it in the TLB
412                 eret
413                 nop
415                 .set    reorder
416                 .set    at
418 END(rm5200_tlbhandler)
420 /*  *********************************************************************
421     *  End
422     ********************************************************************* */