1/* ********************************************************************* 2 * P5064 Board Support Package 3 * 4 * CPU initialization File: rm7000_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 ********************************************************************* */ 49 50#include "sbmips.h" 51#include "bsp_config.h" 52#include "mipsmacros.h" 53#include "exception.h" 54 55 56 .text 57 .set mips64 58 59 60/* ********************************************************************* 61 * Macros 62 ********************************************************************* */ 63 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 68#define LINESIZE 32 69 70 71#define CACHEOP(cachename,op) ((cachename) | ((op) << 2)) 72 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 82 83#define L2C 3 84#define L1C_I 0 85#define L1C_D 1 86 87 88/* 89 * Duplicates from cfe_iocb.h -- warning! 90 */ 91 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 99 100/* ********************************************************************* 101 * Linkage tables 102 ********************************************************************* */ 103 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) 108 109cpuinit_table: 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 114 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) 121 122 123 124/* ********************************************************************* 125 * RM7000_CP0_INIT 126 * 127 * Initialize CP0 registers for an RM7000 core. 128 * 129 * Input parameters: 130 * nothing 131 * 132 * Return value: 133 * nothing 134 ********************************************************************* */ 135 136LEAF(rm7000_cp0_init) 137 138 /* 139 * Set SR and CAUSE to something sensible. 140 */ 141 142 .set noreorder 143 mfc0 t0,C0_PRID 144 mfc0 v0,C0_SR 145 mtc0 zero,C0_WATCHLO 146 mtc0 zero,C0_WATCHHI 147 li t1,-1 148 mtc0 t1,C0_COMPARE 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. 153 .set reorder 154 155 156 mfc0 t1,C0_CONFIG 157 158 mtc0 zero,C0_WATCHLO 159 mtc0 zero,C0_WATCHHI 160 161 /* 162 * make KSEG0 cacheable 163 */ 164 165 and t1,~M_CFG_K0COH 166 or t1,V_CFG_K0COH(K_CFG_K0COH_CACHEABLE) 167 or t1,0x08 /* enable SCache */ 168 and t1,~(1<<12) /* disable TCache */ 169 170 /* 171 * set DDDD rate for CPUs that aren't hardware configured 172 */ 173 174 and t1,~CFG_EPMASK 175 or t1,CFG_EPD 176 177#ifdef __MIPSEB 178 or t1,CFG_BE 179#else 180 and t1,~CFG_BE 181#endif 182 mtc0 t1,C0_CONFIG 183 184 185 /* 186 * initialize tlb 187 */ 188 mtc0 zero,C0_TLBLO0 /* tlblo0 = invalid */ 189 mtc0 zero,C0_TLBLO1 /* tlblo1 = invalid */ 190 mtc0 zero,C0_PGMASK 191 li t8,K1BASE /* tlbhi = impossible vpn */ 192 li t9,(NTLBENTRIES-1) /* index */ 193 194 195 .set noreorder 196 nop 1971: mtc0 t8,C0_TLBHI 198 mtc0 t9,C0_INX 199 addu t8,0x2000 /* inc vpn */ 200 tlbwi 201 bnez t9,1b 202 subu t9,1 # BDSLOT 203 .set reorder 204 205 j ra 206 207END(rm7000_cp0_init) 208 209 210/* ********************************************************************* 211 * RM7000_NULL_INIT 212 * 213 * This stub routine is used by initialization functions that 214 * we leave unimplemented. 215 * 216 * Input parameters: 217 * nothing 218 * 219 * Return value: 220 * nothing 221 ********************************************************************* */ 222 223LEAF(rm7000_null_init) 224 j ra 225END(rm7000_null_init) 226 227 228 229/* ********************************************************************* 230 * RM7000_CPUINIT 231 * 232 * Initialize the CPU core. 233 * 234 * Input parameters: 235 * nothing 236 * 237 * Return value: 238 * nothing 239 ********************************************************************* */ 240 241LEAF(rm7000_cpuinit) 242 243 move k0,ra /* will be trashing RA */ 244 245 /* 246 * Basic CPU initialization 247 */ 248 249 CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT) 250 251 /* 252 * CP0 registers 253 */ 254 255 256#------------------------------------------------------------------------------ 257 258 /* 259 * Init the L1 cache. 260 */ 261 262#if CFG_INIT_L1 263 SETLEDS1('L','1','C','I') 264 CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT) 265#endif 266 267 /* 268 * Init the L2 cache 269 */ 270#if CFG_INIT_L1 271 SETLEDS1('L','2','C','I') 272 CALLINIT_KSEG1(cpuinit_table,R_CPU_L2CINIT) 273#endif 274 275 move ra,k0 /* saved return address */ 276 j ra 277 278 279END(rm7000_cpuinit) 280 281/* ********************************************************************* 282 * RM7000_CPURESTART 283 * 284 * 'Restart' the CPU (reset things back to some sane state after 285 * a program returns to the firmware) 286 * 287 * Input parameters: 288 * nothing 289 * 290 * Return value: 291 * nothing 292 ********************************************************************* */ 293 294LEAF(rm7000_cpurestart) 295 296 move k0,ra 297 298 CALLINIT_KSEG0(cpuinit_table,R_CPU_CP0INIT) 299 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 303 304 move ra,k0 305 j ra 306 307END(rm7000_cpurestart) 308 309 310LEAF(rm7000_cacheops) 311 312 move s0,ra 313 314 move v1,a0 315 316 /* 317 * With no flags, we flush L1D and invalid L1I 318 */ 319 320 bne v1,zero,1f 321 li v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I 3221: 323 324 /* 325 * Flush the D-Cache, since the program we loaded is "data". 326 */ 327 328 and a0,v1,CFE_CACHE_FLUSH_D 329 beq a0,zero,1f 330 jal rm7000_l1cache_flush_d 3311: 332 333 /* 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. 337 */ 338 339 and a0,v1,CFE_CACHE_INVAL_I 340 beq a0,zero,1f 341 jal rm7000_l1cache_inval_i 3421: 343 344 345 /* 346 * Invalidate the L2, if requested. Use this cautiously, 347 * since it invalidates both I and D! 348 */ 349 350 and a0,v1,CFE_CACHE_INVAL_L2 351 beq a0,zero,1f 352 jal rm7000_l2cache_init 3531: 354 355 /* 356 * Invalidate the L2, if requested. Use this cautiously, 357 * since it invalidates both I and D! 358 */ 359 360 and a0,v1,CFE_CACHE_FLUSH_L2 361 beq a0,zero,1f 362 jal rm7000_l2cache_flush /* Trashes T0..T7, V0, A0 */ 3631: 364 365 /* 366 * Invalidate cache range 367 */ 368 369 and a0,v1,CFE_CACHE_INVAL_RANGE 370 beq a0,zero,2f 371 372 move t0,a1 3731: cache CACHEOP(L2C,CACHE_OP_HITINVAL),0(t0) 374 add t0,LINESIZE 375 blt t0,a2,1b 376 377 move t0,a1 3781: cache CACHEOP(L1C_D,CACHE_OP_HITINVAL),0(t0) 379 add t0,LINESIZE 380 blt t0,a2,1b 381 382 /* 383 * Flush cache range 384 */ 385 386 3872: 388 and a0,v1,CFE_CACHE_FLUSH_RANGE 389 beq a0,zero,2f 390 391 move t0,a1 3921: cache CACHEOP(L1C_D,CACHE_OP_HITWRITEBACK_INVAL),0(t0) 393 add t0,LINESIZE 394 blt t0,a2,1b 395 move t0,a1 3961: cache CACHEOP(L2C,CACHE_OP_HITWRITEBACK_INVAL),0(t0) 397 add t0,LINESIZE 398 blt t0,a2,1b 399 400 4012: 402 move ra,s0 403 j ra 404 405END(rm7000_cacheops) 406 407/* ********************************************************************* 408 * RM7000_TLBHANDLER 409 * 410 * This is the TLB exception handler for the RM7000 411 * 412 * Note: only K0 and K1 are available to us at this time. 413 * 414 * Input parameters: 415 * nothing 416 * 417 * Return value: 418 * nothing 419 ********************************************************************* */ 420 421 422LEAF(rm7000_tlbhandler) 423 .set noreorder 424 .set noat 425 426/* 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 431 * of 4KB each. 432 * 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 437 * 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 442 * 1KB boundary). 443 * 444 * To make this work, we'll shift PTEbase to the right, leaving 445 * the bottom ten bits for the page number, as: 446 * 447 * Bits 31..10: PTEbase 448 * Bits 9..4: BadVPN 449 * Bits 3..0: 16 bytes for table entry 450 * 451 * Therefore: 452 * PTEbase gets shifted right 13 bits. 453 * BadVPN gets masked at 6 bits (mask is 0x3F0) 454 * The bottom 4 bits are zero. 455 * 456 * To range check the address, we can shift the Bad VPN 457 * right by 9 bits, and check for values of 0x1000 and 458 * 0x1001. 459 */ 460 461 462 /* 463 * This part range checks the VPN2 field in the 464 * context register. We only handle 465 * VPN2s in the range 0x100000 to 0x1001F0 466 */ 467 dmfc0 k0,C0_TLBHI 468 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 473 beq k0,k1,1f # 474 nop # BDSLOT 475 li k1,0x1001 # 0x1001 is ok 476 beq k0,k1,1f # 477 nop # BDSLOT 478 479 li k0,XTYPE_TLBFILL # all other bits are not 480 j _exc_entry 481 nop # BDSLOT 482 4831: 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. 488 489 dmfc0 k1,C0_CTEXT # Get Context 490 and k1,0x3F0 # Keep only BadVPN2 bits 491 or k1,k0 # Replace PTEBase 492 493 ld k0,0(k1) # Load entrylo0 494 ld k1,8(k1) # Load entrylo1 495 mtc0 k0,C0_TLBLO0 # and write to CP0 496 mtc0 k1,C0_TLBLO1 497 tlbwr # put it in the TLB 498 eret 499 nop 500 501 .set reorder 502 .set at 503 504END(rm7000_tlbhandler) 505 506/* ********************************************************************* 507 * End 508 ********************************************************************* */ 509