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 ********************************************************************* */ 23 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" 30 31 32 .text 33 34 .set mips32 35 36/* ********************************************************************* 37 * Macros 38 ********************************************************************* */ 39 40#define R_CPU_CP0INIT _TBLIDX(0) 41#define R_CPU_L1CINIT _TBLIDX(1) 42#define R_CPU_SETLEDS _TBLIDX(2) 43 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) 50 51cpuinit_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 55 56 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 ********************************************************************* */ 71 72 73LEAF(bcmcore_cp0_init) 74 75 .set noreorder 76 77 mtc0 zero,C0_WATCHLO # Watch registers. 78 mtc0 zero,C0_WATCHHI 79 mtc0 zero,C0_CAUSE # must clear before writing SR 80 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 89 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 991: bne v0,0x00019700,2f # 74k core 100 mfc0 v0,C0_CONFIG,7 101 or v0,(1 << 29) 102 mtc0 v0,C0_CONFIG,7 103 1042: mtc0 zero,C0_COUNT 105 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 # 110 111 li v0,-1 112 mtc0 v0,C0_COMPARE 113 nop 114 115 # 116 # Initialize all the TLB entries to some invalid value 117 # 118 119 mtc0 zero,C0_TLBHI # TLB entry (high half) 120 nop 121 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 128 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 135 136 nop 1371: 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 146 147 148 149 jr ra 150 151 152END(bcmcore_cp0_init) 153 154 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 ********************************************************************* */ 166 167 168LEAF(bcmcore_cpuinit) 169 170 move fp,ra 171 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 180 181END(bcmcore_cpuinit) 182 183 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 ********************************************************************* */ 199 200LEAF(bcmcore_null) 201 202 j ra 203 204END(bcmcore_null) 205 206 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 ********************************************************************* */ 219 220LEAF(bcmcore_cpurestart) 221 222 j ra 223 224END(bcmcore_cpurestart) 225 226 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 ********************************************************************* */ 241 242LEAF(bcmcore_cacheops) 243 244 move s0,ra 245 246 move v1,a0 247 248 /* 249 * With no flags, we flush L1D and invalid L1I 250 */ 251 252 bne v1,zero,1f 253 li v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I 2541: 255 256 /* 257 * Flush the D-Cache, since the program we loaded is "data". 258 */ 259 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 2631: 264 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 */ 270 271 and a0,v1,CFE_CACHE_INVAL_I 272 beq a0,zero,1f 273 jal bcmcore_l1cache_inval_i 2741: 275 276 move ra,s0 277 j ra 278 279END(bcmcore_cacheops) 280 281 282 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 ********************************************************************* */ 296 297 298LEAF(bcmcore_tlbhandler) 299 .set noreorder 300 .set noat 301 302#ifdef BCM4704 303 nop 304#endif 305 306 307/* 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. 313 * 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). 324 * 325 * To make this work, we'll shift PTEbase to the right, leaving 326 * the bottom ten bits for the page number, as: 327 * 328 * Bits 31..10: PTEbase 329 * Bits 9..4: BadVPN 330 * Bits 3..0: 16 bytes for table entry 331 * 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. 336 * 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 */ 341 342 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 349 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 359 360 li k0,XTYPE_TLBFILL # all other bits are not 361 j _exc_entry 362 nop # BDSLOT 363 3641: 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. 369 370 mfc0 k1,C0_CTEXT # Get Context 371 and k1,0x3F0 # Keep only BadVPN2 bits 372 or k1,k0 # Replace PTEBase 373 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 381 382 .set reorder 383 .set at 384 385END(bcmcore_tlbhandler) 386 387 388/* ********************************************************************* 389 * End 390 ********************************************************************* */ 391