1 /* 2 * Misc utility routines for accessing chip-specific features 3 * of the SiliconBackplane-based Broadcom chips. 4 * 5 * Copyright (C) 1999-2009, Broadcom Corporation 6 * 7 * Unless you and Broadcom execute a separate written software license 8 * agreement governing use of this software, this software is licensed to you 9 * under the terms of the GNU General Public License version 2 (the "GPL"), 10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 11 * following added to such license: 12 * 13 * As a special exception, the copyright holders of this software give you 14 * permission to link this software with independent modules, and to copy and 15 * distribute the resulting executable under terms of your choice, provided that 16 * you also meet, for each linked independent module, the terms and conditions of 17 * the license of that module. An independent module is a module which is not 18 * derived from this software. The special exception does not apply to any 19 * modifications of the software. 20 * 21 * Notwithstanding the above, under no circumstances may you combine this 22 * software in any way with any other Broadcom software provided under a license 23 * other than the GPL, without Broadcom's express prior written consent. 24 * 25 * $Id: sbutils.c,v 1.662.4.10.2.7.4.1 2009/09/25 00:32:01 Exp $ 26 */ 27 28 #include <typedefs.h> 29 #include <bcmdefs.h> 30 #include <osl.h> 31 #include <bcmutils.h> 32 #include <siutils.h> 33 #include <bcmdevs.h> 34 #include <hndsoc.h> 35 #include <sbchipc.h> 36 #include <pcicfg.h> 37 #include <sbpcmcia.h> 38 39 #include "siutils_priv.h" 40 41 /* local prototypes */ 42 static uint _sb_coreidx(si_info_t *sii, uint32 sba); 43 static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, 44 uint ncores); 45 static uint32 _sb_coresba(si_info_t *sii); 46 static void *_sb_setcoreidx(si_info_t *sii, uint coreidx); 47 48 #define SET_SBREG(sii, r, mask, val) \ 49 W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val))) 50 #define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) 51 52 /* sonicsrev */ 53 #define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) 54 #define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) 55 56 #define R_SBREG(sii, sbr) sb_read_sbreg((sii), (sbr)) 57 #define W_SBREG(sii, sbr, v) sb_write_sbreg((sii), (sbr), (v)) 58 #define AND_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v))) 59 #define OR_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v))) 60 61 static uint32 62 sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr) 63 { 64 uint8 tmp; 65 uint32 val, intr_val = 0; 66 67 68 /* 69 * compact flash only has 11 bits address, while we needs 12 bits address. 70 * MEM_SEG will be OR'd with other 11 bits address in hardware, 71 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). 72 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special 73 */ 74 if (PCMCIA(sii)) { 75 INTR_OFF(sii, intr_val); 76 tmp = 1; 77 OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); 78 sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ 79 } 80 81 val = R_REG(sii->osh, sbr); 82 83 if (PCMCIA(sii)) { 84 tmp = 0; 85 OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); 86 INTR_RESTORE(sii, intr_val); 87 } 88 89 return (val); 90 } 91 92 static void 93 sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v) 94 { 95 uint8 tmp; 96 volatile uint32 dummy; 97 uint32 intr_val = 0; 98 99 100 /* 101 * compact flash only has 11 bits address, while we needs 12 bits address. 102 * MEM_SEG will be OR'd with other 11 bits address in hardware, 103 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). 104 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special 105 */ 106 if (PCMCIA(sii)) { 107 INTR_OFF(sii, intr_val); 108 tmp = 1; 109 OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); 110 sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ 111 } 112 113 if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) { 114 #ifdef IL_BIGENDIAN 115 dummy = R_REG(sii->osh, sbr); 116 W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); 117 dummy = R_REG(sii->osh, sbr); 118 W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); 119 #else 120 dummy = R_REG(sii->osh, sbr); 121 W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); 122 dummy = R_REG(sii->osh, sbr); 123 W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); 124 #endif /* IL_BIGENDIAN */ 125 } else 126 W_REG(sii->osh, sbr, v); 127 128 if (PCMCIA(sii)) { 129 tmp = 0; 130 OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); 131 INTR_RESTORE(sii, intr_val); 132 } 133 } 134 135 uint 136 sb_coreid(si_t *sih) 137 { 138 si_info_t *sii; 139 sbconfig_t *sb; 140 141 sii = SI_INFO(sih); 142 sb = REGS2SB(sii->curmap); 143 144 return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); 145 } 146 147 uint 148 sb_flag(si_t *sih) 149 { 150 si_info_t *sii; 151 sbconfig_t *sb; 152 153 sii = SI_INFO(sih); 154 sb = REGS2SB(sii->curmap); 155 156 return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK; 157 } 158 159 void 160 sb_setint(si_t *sih, int siflag) 161 { 162 si_info_t *sii; 163 sbconfig_t *sb; 164 uint32 vec; 165 166 sii = SI_INFO(sih); 167 sb = REGS2SB(sii->curmap); 168 169 if (siflag == -1) 170 vec = 0; 171 else 172 vec = 1 << siflag; 173 W_SBREG(sii, &sb->sbintvec, vec); 174 } 175 176 /* return core index of the core with address 'sba' */ 177 static uint 178 _sb_coreidx(si_info_t *sii, uint32 sba) 179 { 180 uint i; 181 182 for (i = 0; i < sii->numcores; i ++) 183 if (sba == sii->common_info->coresba[i]) 184 return i; 185 return BADIDX; 186 } 187 188 /* return core address of the current core */ 189 static uint32 190 _sb_coresba(si_info_t *sii) 191 { 192 uint32 sbaddr; 193 194 195 switch (BUSTYPE(sii->pub.bustype)) { 196 case SI_BUS: { 197 sbconfig_t *sb = REGS2SB(sii->curmap); 198 sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0)); 199 break; 200 } 201 202 case PCI_BUS: 203 sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 204 break; 205 206 case PCMCIA_BUS: { 207 uint8 tmp = 0; 208 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); 209 sbaddr = (uint32)tmp << 12; 210 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); 211 sbaddr |= (uint32)tmp << 16; 212 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); 213 sbaddr |= (uint32)tmp << 24; 214 break; 215 } 216 217 case SPI_BUS: 218 case SDIO_BUS: 219 sbaddr = (uint32)(uintptr)sii->curmap; 220 break; 221 222 223 default: 224 sbaddr = BADCOREADDR; 225 break; 226 } 227 228 return sbaddr; 229 } 230 231 uint 232 sb_corevendor(si_t *sih) 233 { 234 si_info_t *sii; 235 sbconfig_t *sb; 236 237 sii = SI_INFO(sih); 238 sb = REGS2SB(sii->curmap); 239 240 return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); 241 } 242 243 uint 244 sb_corerev(si_t *sih) 245 { 246 si_info_t *sii; 247 sbconfig_t *sb; 248 uint sbidh; 249 250 sii = SI_INFO(sih); 251 sb = REGS2SB(sii->curmap); 252 sbidh = R_SBREG(sii, &sb->sbidhigh); 253 254 return (SBCOREREV(sbidh)); 255 } 256 257 /* set core-specific control flags */ 258 void 259 sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) 260 { 261 si_info_t *sii; 262 sbconfig_t *sb; 263 uint32 w; 264 265 sii = SI_INFO(sih); 266 sb = REGS2SB(sii->curmap); 267 268 ASSERT((val & ~mask) == 0); 269 270 /* mask and set */ 271 w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | 272 (val << SBTML_SICF_SHIFT); 273 W_SBREG(sii, &sb->sbtmstatelow, w); 274 } 275 276 /* set/clear core-specific control flags */ 277 uint32 278 sb_core_cflags(si_t *sih, uint32 mask, uint32 val) 279 { 280 si_info_t *sii; 281 sbconfig_t *sb; 282 uint32 w; 283 284 sii = SI_INFO(sih); 285 sb = REGS2SB(sii->curmap); 286 287 ASSERT((val & ~mask) == 0); 288 289 /* mask and set */ 290 if (mask || val) { 291 w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | 292 (val << SBTML_SICF_SHIFT); 293 W_SBREG(sii, &sb->sbtmstatelow, w); 294 } 295 296 /* return the new value 297 * for write operation, the following readback ensures the completion of write opration. 298 */ 299 return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT); 300 } 301 302 /* set/clear core-specific status flags */ 303 uint32 304 sb_core_sflags(si_t *sih, uint32 mask, uint32 val) 305 { 306 si_info_t *sii; 307 sbconfig_t *sb; 308 uint32 w; 309 310 sii = SI_INFO(sih); 311 sb = REGS2SB(sii->curmap); 312 313 ASSERT((val & ~mask) == 0); 314 ASSERT((mask & ~SISF_CORE_BITS) == 0); 315 316 /* mask and set */ 317 if (mask || val) { 318 w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) | 319 (val << SBTMH_SISF_SHIFT); 320 W_SBREG(sii, &sb->sbtmstatehigh, w); 321 } 322 323 /* return the new value */ 324 return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT); 325 } 326 327 bool 328 sb_iscoreup(si_t *sih) 329 { 330 si_info_t *sii; 331 sbconfig_t *sb; 332 333 sii = SI_INFO(sih); 334 sb = REGS2SB(sii->curmap); 335 336 return ((R_SBREG(sii, &sb->sbtmstatelow) & 337 (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) == 338 (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); 339 } 340 341 /* 342 * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, 343 * switch back to the original core, and return the new value. 344 * 345 * When using the silicon backplane, no fidleing with interrupts or core switches are needed. 346 * 347 * Also, when using pci/pcie, we can optimize away the core switching for pci registers 348 * and (on newer pci cores) chipcommon registers. 349 */ 350 uint 351 sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 352 { 353 uint origidx = 0; 354 uint32 *r = NULL; 355 uint w; 356 uint intr_val = 0; 357 bool fast = FALSE; 358 si_info_t *sii; 359 360 sii = SI_INFO(sih); 361 362 ASSERT(GOODIDX(coreidx)); 363 ASSERT(regoff < SI_CORE_SIZE); 364 ASSERT((val & ~mask) == 0); 365 366 if (coreidx >= SI_MAXCORES) 367 return 0; 368 369 if (BUSTYPE(sii->pub.bustype) == SI_BUS) { 370 /* If internal bus, we can always get at everything */ 371 fast = TRUE; 372 /* map if does not exist */ 373 if (!sii->common_info->regs[coreidx]) { 374 sii->common_info->regs[coreidx] = 375 REG_MAP(sii->common_info->coresba[coreidx], SI_CORE_SIZE); 376 ASSERT(GOODREGS(sii->common_info->regs[coreidx])); 377 } 378 r = (uint32 *)((uchar *)sii->common_info->regs[coreidx] + regoff); 379 } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { 380 /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ 381 382 if ((sii->common_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { 383 /* Chipc registers are mapped at 12KB */ 384 385 fast = TRUE; 386 r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); 387 } else if (sii->pub.buscoreidx == coreidx) { 388 /* pci registers are at either in the last 2KB of an 8KB window 389 * or, in pcie and pci rev 13 at 8KB 390 */ 391 fast = TRUE; 392 if (SI_FAST(sii)) 393 r = (uint32 *)((char *)sii->curmap + 394 PCI_16KB0_PCIREGS_OFFSET + regoff); 395 else 396 r = (uint32 *)((char *)sii->curmap + 397 ((regoff >= SBCONFIGOFF) ? 398 PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + 399 regoff); 400 } 401 } 402 403 if (!fast) { 404 INTR_OFF(sii, intr_val); 405 406 /* save current core index */ 407 origidx = si_coreidx(&sii->pub); 408 409 /* switch core */ 410 r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff); 411 } 412 ASSERT(r != NULL); 413 414 /* mask and set */ 415 if (mask || val) { 416 if (regoff >= SBCONFIGOFF) { 417 w = (R_SBREG(sii, r) & ~mask) | val; 418 W_SBREG(sii, r, w); 419 } else { 420 w = (R_REG(sii->osh, r) & ~mask) | val; 421 W_REG(sii->osh, r, w); 422 } 423 } 424 425 /* readback */ 426 if (regoff >= SBCONFIGOFF) 427 w = R_SBREG(sii, r); 428 else { 429 if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) && 430 (coreidx == SI_CC_IDX) && 431 (regoff == OFFSETOF(chipcregs_t, watchdog))) { 432 w = val; 433 } else 434 w = R_REG(sii->osh, r); 435 } 436 437 if (!fast) { 438 /* restore core index */ 439 if (origidx != coreidx) 440 sb_setcoreidx(&sii->pub, origidx); 441 442 INTR_RESTORE(sii, intr_val); 443 } 444 445 return (w); 446 } 447 448 /* Scan the enumeration space to find all cores starting from the given 449 * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba' 450 * is the default core address at chip POR time and 'regs' is the virtual 451 * address that the default core is mapped at. 'ncores' is the number of 452 * cores expected on bus 'sbba'. It returns the total number of cores 453 * starting from bus 'sbba', inclusive. 454 */ 455 #define SB_MAXBUSES 2 456 static uint 457 _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores) 458 { 459 uint next; 460 uint ncc = 0; 461 uint i; 462 463 if (bus >= SB_MAXBUSES) { 464 SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus)); 465 return 0; 466 } 467 SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores)); 468 469 /* Scan all cores on the bus starting from core 0. 470 * Core addresses must be contiguous on each bus. 471 */ 472 for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) { 473 sii->common_info->coresba[next] = sbba + (i * SI_CORE_SIZE); 474 475 /* keep and reuse the initial register mapping */ 476 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && 477 (sii->common_info->coresba[next] == sba)) { 478 SI_MSG(("_sb_scan: reuse mapped regs %p for core %u\n", regs, next)); 479 sii->common_info->regs[next] = regs; 480 } 481 482 /* change core to 'next' and read its coreid */ 483 sii->curmap = _sb_setcoreidx(sii, next); 484 sii->curidx = next; 485 486 sii->common_info->coreid[next] = sb_coreid(&sii->pub); 487 488 /* core specific processing... */ 489 /* chipc provides # cores */ 490 if (sii->common_info->coreid[next] == CC_CORE_ID) { 491 chipcregs_t *cc = (chipcregs_t *)sii->curmap; 492 uint32 ccrev = sb_corerev(&sii->pub); 493 494 /* determine numcores - this is the total # cores in the chip */ 495 if (((ccrev == 4) || (ccrev >= 6))) 496 numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> 497 CID_CC_SHIFT; 498 else { 499 /* Older chips */ 500 uint chip = sii->pub.chip; 501 502 if (chip == BCM4306_CHIP_ID) /* < 4306c0 */ 503 numcores = 6; 504 else if (chip == BCM4704_CHIP_ID) 505 numcores = 9; 506 else if (chip == BCM5365_CHIP_ID) 507 numcores = 7; 508 else { 509 SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", 510 chip)); 511 ASSERT(0); 512 numcores = 1; 513 } 514 } 515 SI_MSG(("_sb_scan: there are %u cores in the chip %s\n", numcores, 516 sii->pub.issim ? "QT" : "")); 517 } 518 /* scan bridged SB(s) and add results to the end of the list */ 519 else if (sii->common_info->coreid[next] == OCP_CORE_ID) { 520 sbconfig_t *sb = REGS2SB(sii->curmap); 521 uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1); 522 uint nsbcc; 523 524 sii->numcores = next + 1; 525 526 if ((nsbba & 0xfff00000) != SI_ENUM_BASE) 527 continue; 528 nsbba &= 0xfffff000; 529 if (_sb_coreidx(sii, nsbba) != BADIDX) 530 continue; 531 532 nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16; 533 nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc); 534 if (sbba == SI_ENUM_BASE) 535 numcores -= nsbcc; 536 ncc += nsbcc; 537 } 538 } 539 540 SI_MSG(("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba)); 541 542 sii->numcores = i + ncc; 543 return sii->numcores; 544 } 545 546 /* scan the sb enumerated space to identify all cores */ 547 void 548 sb_scan(si_t *sih, void *regs, uint devid) 549 { 550 si_info_t *sii; 551 uint32 origsba; 552 553 sii = SI_INFO(sih); 554 555 /* Save the current core info and validate it later till we know 556 * for sure what is good and what is bad. 557 */ 558 origsba = _sb_coresba(sii); 559 560 /* scan all SB(s) starting from SI_ENUM_BASE */ 561 sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1); 562 } 563 564 /* 565 * This function changes logical "focus" to the indicated core; 566 * must be called with interrupts off. 567 * Moreover, callers should keep interrupts off during switching out of and back to d11 core 568 */ 569 void * 570 sb_setcoreidx(si_t *sih, uint coreidx) 571 { 572 si_info_t *sii; 573 574 sii = SI_INFO(sih); 575 576 if (coreidx >= sii->numcores) 577 return (NULL); 578 579 /* 580 * If the user has provided an interrupt mask enabled function, 581 * then assert interrupts are disabled before switching the core. 582 */ 583 ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); 584 585 sii->curmap = _sb_setcoreidx(sii, coreidx); 586 sii->curidx = coreidx; 587 588 return (sii->curmap); 589 } 590 591 /* This function changes the logical "focus" to the indicated core. 592 * Return the current core's virtual address. 593 */ 594 static void * 595 _sb_setcoreidx(si_info_t *sii, uint coreidx) 596 { 597 uint32 sbaddr = sii->common_info->coresba[coreidx]; 598 void *regs; 599 600 switch (BUSTYPE(sii->pub.bustype)) { 601 case SI_BUS: 602 /* map new one */ 603 if (!sii->common_info->regs[coreidx]) { 604 sii->common_info->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE); 605 ASSERT(GOODREGS(sii->common_info->regs[coreidx])); 606 } 607 regs = sii->common_info->regs[coreidx]; 608 break; 609 610 case PCI_BUS: 611 /* point bar0 window */ 612 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr); 613 regs = sii->curmap; 614 break; 615 616 case PCMCIA_BUS: { 617 uint8 tmp = (sbaddr >> 12) & 0x0f; 618 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); 619 tmp = (sbaddr >> 16) & 0xff; 620 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); 621 tmp = (sbaddr >> 24) & 0xff; 622 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); 623 regs = sii->curmap; 624 break; 625 } 626 case SPI_BUS: 627 case SDIO_BUS: 628 /* map new one */ 629 if (!sii->common_info->regs[coreidx]) { 630 sii->common_info->regs[coreidx] = (void *)(uintptr)sbaddr; 631 ASSERT(GOODREGS(sii->common_info->regs[coreidx])); 632 } 633 regs = sii->common_info->regs[coreidx]; 634 break; 635 636 637 default: 638 ASSERT(0); 639 regs = NULL; 640 break; 641 } 642 643 return regs; 644 } 645 646 /* Return the address of sbadmatch0/1/2/3 register */ 647 static volatile uint32 * 648 sb_admatch(si_info_t *sii, uint asidx) 649 { 650 sbconfig_t *sb; 651 volatile uint32 *addrm; 652 653 sb = REGS2SB(sii->curmap); 654 655 switch (asidx) { 656 case 0: 657 addrm = &sb->sbadmatch0; 658 break; 659 660 case 1: 661 addrm = &sb->sbadmatch1; 662 break; 663 664 case 2: 665 addrm = &sb->sbadmatch2; 666 break; 667 668 case 3: 669 addrm = &sb->sbadmatch3; 670 break; 671 672 default: 673 SI_ERROR(("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx)); 674 return 0; 675 } 676 677 return (addrm); 678 } 679 680 /* Return the number of address spaces in current core */ 681 int 682 sb_numaddrspaces(si_t *sih) 683 { 684 si_info_t *sii; 685 sbconfig_t *sb; 686 687 sii = SI_INFO(sih); 688 sb = REGS2SB(sii->curmap); 689 690 /* + 1 because of enumeration space */ 691 return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1; 692 } 693 694 /* Return the address of the nth address space in the current core */ 695 uint32 696 sb_addrspace(si_t *sih, uint asidx) 697 { 698 si_info_t *sii; 699 700 sii = SI_INFO(sih); 701 702 return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx)))); 703 } 704 705 /* Return the size of the nth address space in the current core */ 706 uint32 707 sb_addrspacesize(si_t *sih, uint asidx) 708 { 709 si_info_t *sii; 710 711 sii = SI_INFO(sih); 712 713 return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx)))); 714 } 715 716 717 /* do buffered registers update */ 718 void 719 sb_commit(si_t *sih) 720 { 721 si_info_t *sii; 722 uint origidx; 723 uint intr_val = 0; 724 725 sii = SI_INFO(sih); 726 727 origidx = sii->curidx; 728 ASSERT(GOODIDX(origidx)); 729 730 INTR_OFF(sii, intr_val); 731 732 /* switch over to chipcommon core if there is one, else use pci */ 733 if (sii->pub.ccrev != NOREV) { 734 chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 735 736 /* do the buffer registers update */ 737 W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT); 738 W_REG(sii->osh, &ccregs->broadcastdata, 0x0); 739 } else 740 ASSERT(0); 741 742 /* restore core index */ 743 sb_setcoreidx(sih, origidx); 744 INTR_RESTORE(sii, intr_val); 745 } 746 747 void 748 sb_core_disable(si_t *sih, uint32 bits) 749 { 750 si_info_t *sii; 751 volatile uint32 dummy; 752 sbconfig_t *sb; 753 754 sii = SI_INFO(sih); 755 756 ASSERT(GOODREGS(sii->curmap)); 757 sb = REGS2SB(sii->curmap); 758 759 /* if core is already in reset, just return */ 760 if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET) 761 return; 762 763 /* if clocks are not enabled, put into reset and return */ 764 if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0) 765 goto disable; 766 767 /* set target reject and spin until busy is clear (preserve core-specific bits) */ 768 OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ); 769 dummy = R_SBREG(sii, &sb->sbtmstatelow); 770 OSL_DELAY(1); 771 SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000); 772 if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY) 773 SI_ERROR(("%s: target state still busy\n", __FUNCTION__)); 774 775 if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) { 776 OR_SBREG(sii, &sb->sbimstate, SBIM_RJ); 777 dummy = R_SBREG(sii, &sb->sbimstate); 778 OSL_DELAY(1); 779 SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000); 780 } 781 782 /* set reset and reject while enabling the clocks */ 783 W_SBREG(sii, &sb->sbtmstatelow, 784 (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | 785 SBTML_REJ | SBTML_RESET)); 786 dummy = R_SBREG(sii, &sb->sbtmstatelow); 787 OSL_DELAY(10); 788 789 /* don't forget to clear the initiator reject bit */ 790 if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) 791 AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ); 792 793 disable: 794 /* leave reset and reject asserted */ 795 W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET)); 796 OSL_DELAY(1); 797 } 798 799 /* reset and re-enable a core 800 * inputs: 801 * bits - core specific bits that are set during and after reset sequence 802 * resetbits - core specific bits that are set only during reset sequence 803 */ 804 void 805 sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits) 806 { 807 si_info_t *sii; 808 sbconfig_t *sb; 809 volatile uint32 dummy; 810 811 sii = SI_INFO(sih); 812 ASSERT(GOODREGS(sii->curmap)); 813 sb = REGS2SB(sii->curmap); 814 815 /* 816 * Must do the disable sequence first to work for arbitrary current core state. 817 */ 818 sb_core_disable(sih, (bits | resetbits)); 819 820 /* 821 * Now do the initialization sequence. 822 */ 823 824 /* set reset while enabling the clock and forcing them on throughout the core */ 825 W_SBREG(sii, &sb->sbtmstatelow, 826 (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | 827 SBTML_RESET)); 828 dummy = R_SBREG(sii, &sb->sbtmstatelow); 829 OSL_DELAY(1); 830 831 if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) { 832 W_SBREG(sii, &sb->sbtmstatehigh, 0); 833 } 834 if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) { 835 AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO)); 836 } 837 838 /* clear reset and allow it to propagate throughout the core */ 839 W_SBREG(sii, &sb->sbtmstatelow, 840 ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); 841 dummy = R_SBREG(sii, &sb->sbtmstatelow); 842 OSL_DELAY(1); 843 844 /* leave clock enabled */ 845 W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); 846 dummy = R_SBREG(sii, &sb->sbtmstatelow); 847 OSL_DELAY(1); 848 } 849 850 void 851 sb_core_tofixup(si_t *sih) 852 { 853 si_info_t *sii; 854 sbconfig_t *sb; 855 856 sii = SI_INFO(sih); 857 858 if ((BUSTYPE(sii->pub.bustype) != PCI_BUS) || PCIE(sii) || 859 (PCI(sii) && (sii->pub.buscorerev >= 5))) 860 return; 861 862 ASSERT(GOODREGS(sii->curmap)); 863 sb = REGS2SB(sii->curmap); 864 865 if (BUSTYPE(sii->pub.bustype) == SI_BUS) { 866 SET_SBREG(sii, &sb->sbimconfiglow, 867 SBIMCL_RTO_MASK | SBIMCL_STO_MASK, 868 (0x5 << SBIMCL_RTO_SHIFT) | 0x3); 869 } else { 870 if (sb_coreid(sih) == PCI_CORE_ID) { 871 SET_SBREG(sii, &sb->sbimconfiglow, 872 SBIMCL_RTO_MASK | SBIMCL_STO_MASK, 873 (0x3 << SBIMCL_RTO_SHIFT) | 0x2); 874 } else { 875 SET_SBREG(sii, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); 876 } 877 } 878 879 sb_commit(sih); 880 } 881 882 /* 883 * Set the initiator timeout for the "master core". 884 * The master core is defined to be the core in control 885 * of the chip and so it issues accesses to non-memory 886 * locations (Because of dma *any* core can access memeory). 887 * 888 * The routine uses the bus to decide who is the master: 889 * SI_BUS => mips 890 * JTAG_BUS => chipc 891 * PCI_BUS => pci or pcie 892 * PCMCIA_BUS => pcmcia 893 * SDIO_BUS => pcmcia 894 * 895 * This routine exists so callers can disable initiator 896 * timeouts so accesses to very slow devices like otp 897 * won't cause an abort. The routine allows arbitrary 898 * settings of the service and request timeouts, though. 899 * 900 * Returns the timeout state before changing it or -1 901 * on error. 902 */ 903 904 #define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) 905 906 uint32 907 sb_set_initiator_to(si_t *sih, uint32 to, uint idx) 908 { 909 si_info_t *sii; 910 uint origidx; 911 uint intr_val = 0; 912 uint32 tmp, ret = 0xffffffff; 913 sbconfig_t *sb; 914 915 sii = SI_INFO(sih); 916 917 if ((to & ~TO_MASK) != 0) 918 return ret; 919 920 /* Figure out the master core */ 921 if (idx == BADIDX) { 922 switch (BUSTYPE(sii->pub.bustype)) { 923 case PCI_BUS: 924 idx = sii->pub.buscoreidx; 925 break; 926 case JTAG_BUS: 927 idx = SI_CC_IDX; 928 break; 929 case PCMCIA_BUS: 930 case SDIO_BUS: 931 idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0); 932 break; 933 case SI_BUS: 934 idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0); 935 break; 936 default: 937 ASSERT(0); 938 } 939 if (idx == BADIDX) 940 return ret; 941 } 942 943 INTR_OFF(sii, intr_val); 944 origidx = si_coreidx(sih); 945 946 sb = REGS2SB(sb_setcoreidx(sih, idx)); 947 948 tmp = R_SBREG(sii, &sb->sbimconfiglow); 949 ret = tmp & TO_MASK; 950 W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); 951 952 sb_commit(sih); 953 sb_setcoreidx(sih, origidx); 954 INTR_RESTORE(sii, intr_val); 955 return ret; 956 } 957 958 uint32 959 sb_base(uint32 admatch) 960 { 961 uint32 base; 962 uint type; 963 964 type = admatch & SBAM_TYPE_MASK; 965 ASSERT(type < 3); 966 967 base = 0; 968 969 if (type == 0) { 970 base = admatch & SBAM_BASE0_MASK; 971 } else if (type == 1) { 972 ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ 973 base = admatch & SBAM_BASE1_MASK; 974 } else if (type == 2) { 975 ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ 976 base = admatch & SBAM_BASE2_MASK; 977 } 978 979 return (base); 980 } 981 982 uint32 983 sb_size(uint32 admatch) 984 { 985 uint32 size; 986 uint type; 987 988 type = admatch & SBAM_TYPE_MASK; 989 ASSERT(type < 3); 990 991 size = 0; 992 993 if (type == 0) { 994 size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); 995 } else if (type == 1) { 996 ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ 997 size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); 998 } else if (type == 2) { 999 ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ 1000 size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); 1001 } 1002 1003 return (size); 1004 } 1005