1 /* *********************************************************************
2 * P5064 Board Support Package
4 * CPU initialization File: rm7000_cpuinit.S
6 * This module contains code to initialize the CPU.
8 * Note: all the routines in this module rely on registers only,
9 * since DRAM may not be active yet.
11 * Author: Mitch Lichtenberg (mpl@broadcom.com)
13 *********************************************************************
15 * Copyright 2000,2001,2002,2003
16 * Broadcom Corporation. All rights reserved.
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.
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.
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.
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 ********************************************************************* */
51 #include "bsp_config.h"
52 #include "mipsmacros.h"
53 #include "exception.h"
60 /* *********************************************************************
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
71 #define CACHEOP(cachename,op) ((cachename) | ((op) << 2))
73 #define CACHE_OP_IDXINVAL 0
74 #define CACHE_OP_IDXLOADTAG 1
75 #define CACHE_OP_IDXSTORETAG 2
76 #define CACHE_OP_IMPLRSVD 3
77 #define CACHE_OP_HITINVAL 4
78 #define CACHE_OP_FILL 5
79 #define CACHE_OP_HITWRITEBACK_INVAL 5
80 #define CACHE_OP_HITWRITEBACK 6
81 #define CACHE_OP_FETCHLOCK 7
89 * Duplicates from cfe_iocb.h -- warning!
92 #define CFE_CACHE_FLUSH_D 1
93 #define CFE_CACHE_INVAL_I 2
94 #define CFE_CACHE_INVAL_D 4
95 #define CFE_CACHE_INVAL_L2 8
96 #define CFE_CACHE_FLUSH_L2 16
97 #define CFE_CACHE_INVAL_RANGE 32
98 #define CFE_CACHE_FLUSH_RANGE 64
100 /* *********************************************************************
102 ********************************************************************* */
104 #define R_CPU_CP0INIT _TBLIDX(0)
105 #define R_CPU_L1CINIT _TBLIDX(1)
106 #define R_CPU_L2CINIT _TBLIDX(2)
107 #define R_CPU_SETLEDS _TBLIDX(3)
110 _LONG_ rm7000_cp0_init # [ 0] R_CPU_CP0INIT
111 _LONG_ rm7000_l1cache_init # [ 1] R_CPU_L1CINIT
112 _LONG_ rm7000_l2cache_init # [ 1] R_CPU_L2CINIT
113 _LONG_ board_setleds # [ 3] R_CPU_SETLEDS
115 #define SETLEDS1(a,b,c,d) \
116 li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
117 CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
118 #define SETLEDS(a,b,c,d) \
119 li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
120 CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
124 /* *********************************************************************
127 * Initialize CP0 registers for an RM7000 core.
134 ********************************************************************* */
136 LEAF(rm7000_cp0_init)
139 * Set SR and CAUSE to something sensible.
149 and v0,M_SR_SR # preserve Soft Reset
150 or v0,M_SR_BEV # set Boot Exceptions
151 mtc0 zero,C0_CAUSE # Must clear WP before
152 mtc0 v0,C0_SR # writing STATUS register.
162 * make KSEG0 cacheable
166 or t1,V_CFG_K0COH(K_CFG_K0COH_CACHEABLE)
167 or t1,0x08 /* enable SCache */
168 and t1,~(1<<12) /* disable TCache */
171 * set DDDD rate for CPUs that aren't hardware configured
188 mtc0 zero,C0_TLBLO0 /* tlblo0 = invalid */
189 mtc0 zero,C0_TLBLO1 /* tlblo1 = invalid */
191 li t8,K1BASE /* tlbhi = impossible vpn */
192 li t9,(NTLBENTRIES-1) /* index */
199 addu t8,0x2000 /* inc vpn */
210 /* *********************************************************************
213 * This stub routine is used by initialization functions that
214 * we leave unimplemented.
221 ********************************************************************* */
223 LEAF(rm7000_null_init)
225 END(rm7000_null_init)
229 /* *********************************************************************
232 * Initialize the CPU core.
239 ********************************************************************* */
243 move k0,ra /* will be trashing RA */
246 * Basic CPU initialization
249 CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
256 #------------------------------------------------------------------------------
263 SETLEDS1('L','1','C','I')
264 CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
271 SETLEDS1('L','2','C','I')
272 CALLINIT_KSEG1(cpuinit_table,R_CPU_L2CINIT)
275 move ra,k0 /* saved return address */
281 /* *********************************************************************
284 * 'Restart' the CPU (reset things back to some sane state after
285 * a program returns to the firmware)
292 ********************************************************************* */
294 LEAF(rm7000_cpurestart)
298 CALLINIT_KSEG0(cpuinit_table,R_CPU_CP0INIT)
300 LR v0,cfe_pagetable # reestablish
301 dsll v0,v0,13 # see mips_arena.c for this
302 dmtc0 v0,C0_CTEXT # boot area TLBs
307 END(rm7000_cpurestart)
310 LEAF(rm7000_cacheops)
317 * With no flags, we flush L1D and invalid L1I
321 li v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
325 * Flush the D-Cache, since the program we loaded is "data".
328 and a0,v1,CFE_CACHE_FLUSH_D
330 jal rm7000_l1cache_flush_d
334 * Invalidate the I-Cache, so that addresses in the program
335 * region will miss and need to be filled from the data we
336 * just flushed above.
339 and a0,v1,CFE_CACHE_INVAL_I
341 jal rm7000_l1cache_inval_i
346 * Invalidate the L2, if requested. Use this cautiously,
347 * since it invalidates both I and D!
350 and a0,v1,CFE_CACHE_INVAL_L2
352 jal rm7000_l2cache_init
356 * Invalidate the L2, if requested. Use this cautiously,
357 * since it invalidates both I and D!
360 and a0,v1,CFE_CACHE_FLUSH_L2
362 jal rm7000_l2cache_flush /* Trashes T0..T7, V0, A0 */
366 * Invalidate cache range
369 and a0,v1,CFE_CACHE_INVAL_RANGE
373 1: cache CACHEOP(L2C,CACHE_OP_HITINVAL),0(t0)
378 1: cache CACHEOP(L1C_D,CACHE_OP_HITINVAL),0(t0)
388 and a0,v1,CFE_CACHE_FLUSH_RANGE
392 1: cache CACHEOP(L1C_D,CACHE_OP_HITWRITEBACK_INVAL),0(t0)
396 1: cache CACHEOP(L2C,CACHE_OP_HITWRITEBACK_INVAL),0(t0)
407 /* *********************************************************************
410 * This is the TLB exception handler for the RM7000
412 * Note: only K0 and K1 are available to us at this time.
419 ********************************************************************* */
422 LEAF(rm7000_tlbhandler)
427 * This requires a bit of explanation: We only support 256KB
428 * of mapped space for the boot program. This space will be
429 * mapped from 0x2000_0000 to 0x2004_0000 to some physical
430 * memory allocated by the firmware. This is 64 pages
433 * We know our BadVPN2 will be in the range
434 * 0x100000 to 0x1001F0, since the memory is mapped from
435 * 0x2000_0000 to 0x2004_0000. BadVPN2 plus the four bits
436 * of zeroes at the end are bits 31..9
438 * We also want to place the PTEbase on something other than
439 * a 16MB boundary. Each entry is 16 bytes, and there
440 * are 64 entries, so we need only 10 bits to address
441 * the entire table (it can therefore be aligned on a
444 * To make this work, we'll shift PTEbase to the right, leaving
445 * the bottom ten bits for the page number, as:
447 * Bits 31..10: PTEbase
449 * Bits 3..0: 16 bytes for table entry
452 * PTEbase gets shifted right 13 bits.
453 * BadVPN gets masked at 6 bits (mask is 0x3F0)
454 * The bottom 4 bits are zero.
456 * To range check the address, we can shift the Bad VPN
457 * right by 9 bits, and check for values of 0x1000 and
463 * This part range checks the VPN2 field in the
464 * context register. We only handle
465 * VPN2s in the range 0x100000 to 0x1001F0
469 dmfc0 k0,C0_CTEXT # Get context
470 dsra k0,8 # keep hi part
471 and k0,0x1FFF # of VPN2
472 li k1,0x1000 # 0x1000 is ok
475 li k1,0x1001 # 0x1001 is ok
479 li k0,XTYPE_TLBFILL # all other bits are not
483 1: dmfc0 k0,C0_CTEXT # Get context
484 dsra k0,13 # Shift PTEbase
485 li k1,0x3FF # Generate mask to kill
486 not k1 # BadVPN2 bits
487 and k0,k1 # keep only PTEBase part.
489 dmfc0 k1,C0_CTEXT # Get Context
490 and k1,0x3F0 # Keep only BadVPN2 bits
491 or k1,k0 # Replace PTEBase
493 ld k0,0(k1) # Load entrylo0
494 ld k1,8(k1) # Load entrylo1
495 mtc0 k0,C0_TLBLO0 # and write to CP0
497 tlbwr # put it in the TLB
504 END(rm7000_tlbhandler)
506 /* *********************************************************************
508 ********************************************************************* */