1 /* 2 * Misc utility routines for accessing chip-specific features 3 * of the SiliconBackplane-based Broadcom chips. 4 * 5 * Copyright (C) 1999-2010, 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: siutils.c,v 1.662.4.4.4.16.4.26 2010/02/01 05:51:56 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 #include <sbsocram.h> 39 #include <bcmsdh.h> 40 #include <sdio.h> 41 #include <sbsdio.h> 42 #include <sbhnddma.h> 43 #include <sbsdpcmdev.h> 44 #include <bcmsdpcm.h> 45 #include <hndpmu.h> 46 47 #include "siutils_priv.h" 48 49 /* local prototypes */ 50 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 51 uint bustype, void *sdh, char **vars, uint *varsz); 52 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); 53 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 54 uint *origidx, void *regs); 55 56 57 /* global variable to indicate reservation/release of gpio's */ 58 static uint32 si_gpioreservation = 0; 59 static void *common_info_alloced = NULL; 60 61 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */ 62 63 /* 64 * Allocate a si handle. 65 * devid - pci device id (used to determine chip#) 66 * osh - opaque OS handle 67 * regs - virtual address of initial core registers 68 * bustype - pci/pcmcia/sb/sdio/etc 69 * vars - pointer to a pointer area for "environment" variables 70 * varsz - pointer to int to return the size of the vars 71 */ 72 si_t * 73 si_attach(uint devid, osl_t *osh, void *regs, 74 uint bustype, void *sdh, char **vars, uint *varsz) 75 { 76 si_info_t *sii; 77 78 /* alloc si_info_t */ 79 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { 80 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); 81 return (NULL); 82 } 83 84 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { 85 if (NULL != sii->common_info) 86 MFREE(osh, sii->common_info, sizeof(si_common_info_t)); 87 MFREE(osh, sii, sizeof(si_info_t)); 88 return (NULL); 89 } 90 sii->vars = vars ? *vars : NULL; 91 sii->varsz = varsz ? *varsz : 0; 92 93 return (si_t *)sii; 94 } 95 96 /* global kernel resource */ 97 static si_info_t ksii; 98 99 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ 100 101 /* generic kernel variant of si_attach() */ 102 si_t * 103 si_kattach(osl_t *osh) 104 { 105 static bool ksii_attached = FALSE; 106 107 if (!ksii_attached) { 108 void *regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 109 110 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, 111 SI_BUS, NULL, 112 osh != SI_OSH ? &ksii.vars : NULL, 113 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { 114 if (NULL != ksii.common_info) 115 MFREE(osh, ksii.common_info, sizeof(si_common_info_t)); 116 SI_ERROR(("si_kattach: si_doattach failed\n")); 117 REG_UNMAP(regs); 118 return NULL; 119 } 120 REG_UNMAP(regs); 121 122 /* save ticks normalized to ms for si_watchdog_ms() */ 123 if (PMUCTL_ENAB(&ksii.pub)) { 124 /* based on 32KHz ILP clock */ 125 wd_msticks = 32; 126 } else { 127 wd_msticks = ALP_CLOCK / 1000; 128 } 129 130 ksii_attached = TRUE; 131 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", 132 ksii.pub.ccrev, wd_msticks)); 133 } 134 135 return &ksii.pub; 136 } 137 138 139 static bool 140 si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) 141 { 142 /* need to set memseg flag for CF card first before any sb registers access */ 143 if (BUSTYPE(bustype) == PCMCIA_BUS) 144 sii->memseg = TRUE; 145 146 147 if (BUSTYPE(bustype) == SDIO_BUS) { 148 int err; 149 uint8 clkset; 150 151 /* Try forcing SDIO core to do ALPAvail request only */ 152 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; 153 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); 154 if (!err) { 155 uint8 clkval; 156 157 /* If register supported, wait for ALPAvail and then force ALP */ 158 clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL); 159 if ((clkval & ~SBSDIO_AVBITS) == clkset) { 160 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 161 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), 162 PMU_MAX_TRANSITION_DLY); 163 if (!SBSDIO_ALPAV(clkval)) { 164 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", 165 clkval)); 166 return FALSE; 167 } 168 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; 169 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 170 clkset, &err); 171 OSL_DELAY(65); 172 } 173 } 174 175 /* Also, disable the extra SDIO pull-ups */ 176 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); 177 } 178 179 180 return TRUE; 181 } 182 183 static bool 184 si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 185 uint *origidx, void *regs) 186 { 187 bool pci, pcie; 188 uint i; 189 uint pciidx, pcieidx, pcirev, pcierev; 190 191 cc = si_setcoreidx(&sii->pub, SI_CC_IDX); 192 ASSERT((uintptr)cc); 193 194 /* get chipcommon rev */ 195 sii->pub.ccrev = (int)si_corerev(&sii->pub); 196 197 /* get chipcommon chipstatus */ 198 if (sii->pub.ccrev >= 11) 199 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); 200 201 /* get chipcommon capabilites */ 202 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); 203 204 /* get pmu rev and caps */ 205 if (sii->pub.cccaps & CC_CAP_PMU) { 206 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); 207 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; 208 } 209 210 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", 211 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, 212 sii->pub.pmucaps)); 213 214 /* figure out bus/orignal core idx */ 215 sii->pub.buscoretype = NODEV_CORE_ID; 216 sii->pub.buscorerev = NOREV; 217 sii->pub.buscoreidx = BADIDX; 218 219 pci = pcie = FALSE; 220 pcirev = pcierev = NOREV; 221 pciidx = pcieidx = BADIDX; 222 223 for (i = 0; i < sii->numcores; i++) { 224 uint cid, crev; 225 226 si_setcoreidx(&sii->pub, i); 227 cid = si_coreid(&sii->pub); 228 crev = si_corerev(&sii->pub); 229 230 /* Display cores found */ 231 SI_MSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", 232 i, cid, crev, sii->common_info->coresba[i], sii->common_info->regs[i])); 233 234 if (BUSTYPE(bustype) == PCI_BUS) { 235 if (cid == PCI_CORE_ID) { 236 pciidx = i; 237 pcirev = crev; 238 pci = TRUE; 239 } else if (cid == PCIE_CORE_ID) { 240 pcieidx = i; 241 pcierev = crev; 242 pcie = TRUE; 243 } 244 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && 245 (cid == PCMCIA_CORE_ID)) { 246 sii->pub.buscorerev = crev; 247 sii->pub.buscoretype = cid; 248 sii->pub.buscoreidx = i; 249 } 250 else if (((BUSTYPE(bustype) == SDIO_BUS) || 251 (BUSTYPE(bustype) == SPI_BUS)) && 252 ((cid == PCMCIA_CORE_ID) || 253 (cid == SDIOD_CORE_ID))) { 254 sii->pub.buscorerev = crev; 255 sii->pub.buscoretype = cid; 256 sii->pub.buscoreidx = i; 257 } 258 259 /* find the core idx before entering this func. */ 260 if ((savewin && (savewin == sii->common_info->coresba[i])) || 261 (regs == sii->common_info->regs[i])) 262 *origidx = i; 263 } 264 265 266 SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, 267 sii->pub.buscorerev)); 268 269 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && 270 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (sii->pub.chiprev <= 3)) 271 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); 272 273 274 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was 275 * already running. 276 */ 277 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { 278 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || 279 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) 280 si_core_disable(&sii->pub, 0); 281 } 282 283 /* return to the original core */ 284 si_setcoreidx(&sii->pub, *origidx); 285 286 return TRUE; 287 } 288 289 290 291 static si_info_t * 292 si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 293 uint bustype, void *sdh, char **vars, uint *varsz) 294 { 295 struct si_pub *sih = &sii->pub; 296 uint32 w, savewin; 297 chipcregs_t *cc; 298 char *pvars = NULL; 299 uint origidx; 300 301 ASSERT(GOODREGS(regs)); 302 303 bzero((uchar*)sii, sizeof(si_info_t)); 304 305 306 { 307 if (NULL == (common_info_alloced = (void *)MALLOC(osh, sizeof(si_common_info_t)))) { 308 SI_ERROR(("si_doattach: malloc failed! malloced %dbytes\n", MALLOCED(osh))); 309 return (NULL); 310 } 311 bzero((uchar*)(common_info_alloced), sizeof(si_common_info_t)); 312 } 313 sii->common_info = (si_common_info_t *)common_info_alloced; 314 sii->common_info->attach_count++; 315 316 savewin = 0; 317 318 sih->buscoreidx = BADIDX; 319 320 sii->curmap = regs; 321 sii->sdh = sdh; 322 sii->osh = osh; 323 324 325 /* find Chipcommon address */ 326 if (bustype == PCI_BUS) { 327 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 328 if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) 329 savewin = SI_ENUM_BASE; 330 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); 331 cc = (chipcregs_t *)regs; 332 } else 333 if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { 334 cc = (chipcregs_t *)sii->curmap; 335 } else { 336 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 337 } 338 339 sih->bustype = bustype; 340 if (bustype != BUSTYPE(bustype)) { 341 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", 342 bustype, BUSTYPE(bustype))); 343 return NULL; 344 } 345 346 /* bus/core/clk setup for register access */ 347 if (!si_buscore_prep(sii, bustype, devid, sdh)) { 348 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); 349 return NULL; 350 } 351 352 /* ChipID recognition. 353 * We assume we can read chipid at offset 0 from the regs arg. 354 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), 355 * some way of recognizing them needs to be added here. 356 */ 357 w = R_REG(osh, &cc->chipid); 358 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 359 /* Might as wll fill in chip id rev & pkg */ 360 sih->chip = w & CID_ID_MASK; 361 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; 362 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; 363 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) 364 sih->chippkg = BCM4329_182PIN_PKG_ID; 365 sih->issim = IS_SIM(sih->chippkg); 366 367 /* scan for cores */ 368 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { 369 SI_MSG(("Found chip type SB (0x%08x)\n", w)); 370 sb_scan(&sii->pub, regs, devid); 371 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { 372 SI_MSG(("Found chip type AI (0x%08x)\n", w)); 373 /* pass chipc address instead of original core base */ 374 ai_scan(&sii->pub, (void *)cc, devid); 375 } else { 376 SI_ERROR(("Found chip of unkown type (0x%08x)\n", w)); 377 return NULL; 378 } 379 /* no cores found, bail out */ 380 if (sii->numcores == 0) { 381 SI_ERROR(("si_doattach: could not find any cores\n")); 382 return NULL; 383 } 384 /* bus/core/clk setup */ 385 origidx = SI_CC_IDX; 386 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { 387 SI_ERROR(("si_doattach: si_buscore_setup failed\n")); 388 return NULL; 389 } 390 391 pvars = NULL; 392 393 394 395 if (sii->pub.ccrev >= 20) { 396 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 397 W_REG(osh, &cc->gpiopullup, 0); 398 W_REG(osh, &cc->gpiopulldown, 0); 399 si_setcoreidx(sih, origidx); 400 } 401 402 /* Skip PMU initialization from the Dongle Host. 403 * Firmware will take care of it when it comes up. 404 */ 405 406 407 408 return (sii); 409 } 410 411 /* may be called with core in reset */ 412 void 413 si_detach(si_t *sih) 414 { 415 si_info_t *sii; 416 uint idx; 417 418 sii = SI_INFO(sih); 419 420 if (sii == NULL) 421 return; 422 423 if (BUSTYPE(sih->bustype) == SI_BUS) 424 for (idx = 0; idx < SI_MAXCORES; idx++) 425 if (sii->common_info->regs[idx]) { 426 REG_UNMAP(sii->common_info->regs[idx]); 427 sii->common_info->regs[idx] = NULL; 428 } 429 430 431 if (1 == sii->common_info->attach_count--) { 432 MFREE(sii->osh, sii->common_info, sizeof(si_common_info_t)); 433 common_info_alloced = NULL; 434 } 435 436 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) 437 if (sii != &ksii) 438 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ 439 MFREE(sii->osh, sii, sizeof(si_info_t)); 440 } 441 442 void * 443 si_osh(si_t *sih) 444 { 445 si_info_t *sii; 446 447 sii = SI_INFO(sih); 448 return sii->osh; 449 } 450 451 void 452 si_setosh(si_t *sih, osl_t *osh) 453 { 454 si_info_t *sii; 455 456 sii = SI_INFO(sih); 457 if (sii->osh != NULL) { 458 SI_ERROR(("osh is already set....\n")); 459 ASSERT(!sii->osh); 460 } 461 sii->osh = osh; 462 } 463 464 /* register driver interrupt disabling and restoring callback functions */ 465 void 466 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, 467 void *intrsenabled_fn, void *intr_arg) 468 { 469 si_info_t *sii; 470 471 sii = SI_INFO(sih); 472 sii->intr_arg = intr_arg; 473 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; 474 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; 475 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; 476 /* save current core id. when this function called, the current core 477 * must be the core which provides driver functions(il, et, wl, etc.) 478 */ 479 sii->dev_coreid = sii->common_info->coreid[sii->curidx]; 480 } 481 482 void 483 si_deregister_intr_callback(si_t *sih) 484 { 485 si_info_t *sii; 486 487 sii = SI_INFO(sih); 488 sii->intrsoff_fn = NULL; 489 } 490 491 uint 492 si_intflag(si_t *sih) 493 { 494 si_info_t *sii = SI_INFO(sih); 495 if (CHIPTYPE(sih->socitype) == SOCI_SB) { 496 sbconfig_t *ccsbr = (sbconfig_t *)((uintptr)((ulong) 497 (sii->common_info->coresba[SI_CC_IDX]) + SBCONFIGOFF)); 498 return R_REG(sii->osh, &ccsbr->sbflagst); 499 } else if (CHIPTYPE(sih->socitype) == SOCI_AI) 500 return R_REG(sii->osh, ((uint32 *)(uintptr) 501 (sii->common_info->oob_router + OOB_STATUSA))); 502 else { 503 ASSERT(0); 504 return 0; 505 } 506 } 507 508 uint 509 si_flag(si_t *sih) 510 { 511 if (CHIPTYPE(sih->socitype) == SOCI_SB) 512 return sb_flag(sih); 513 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 514 return ai_flag(sih); 515 else { 516 ASSERT(0); 517 return 0; 518 } 519 } 520 521 void 522 si_setint(si_t *sih, int siflag) 523 { 524 if (CHIPTYPE(sih->socitype) == SOCI_SB) 525 sb_setint(sih, siflag); 526 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 527 ai_setint(sih, siflag); 528 else 529 ASSERT(0); 530 } 531 532 uint 533 si_coreid(si_t *sih) 534 { 535 si_info_t *sii; 536 537 sii = SI_INFO(sih); 538 return sii->common_info->coreid[sii->curidx]; 539 } 540 541 uint 542 si_coreidx(si_t *sih) 543 { 544 si_info_t *sii; 545 546 sii = SI_INFO(sih); 547 return sii->curidx; 548 } 549 550 /* return the core-type instantiation # of the current core */ 551 uint 552 si_coreunit(si_t *sih) 553 { 554 si_info_t *sii; 555 uint idx; 556 uint coreid; 557 uint coreunit; 558 uint i; 559 560 sii = SI_INFO(sih); 561 coreunit = 0; 562 563 idx = sii->curidx; 564 565 ASSERT(GOODREGS(sii->curmap)); 566 coreid = si_coreid(sih); 567 568 /* count the cores of our type */ 569 for (i = 0; i < idx; i++) 570 if (sii->common_info->coreid[i] == coreid) 571 coreunit++; 572 573 return (coreunit); 574 } 575 576 uint 577 si_corevendor(si_t *sih) 578 { 579 if (CHIPTYPE(sih->socitype) == SOCI_SB) 580 return sb_corevendor(sih); 581 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 582 return ai_corevendor(sih); 583 else { 584 ASSERT(0); 585 return 0; 586 } 587 } 588 589 bool 590 si_backplane64(si_t *sih) 591 { 592 return ((sih->cccaps & CC_CAP_BKPLN64) != 0); 593 } 594 595 uint 596 si_corerev(si_t *sih) 597 { 598 if (CHIPTYPE(sih->socitype) == SOCI_SB) 599 return sb_corerev(sih); 600 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 601 return ai_corerev(sih); 602 else { 603 ASSERT(0); 604 return 0; 605 } 606 } 607 608 /* return index of coreid or BADIDX if not found */ 609 uint 610 si_findcoreidx(si_t *sih, uint coreid, uint coreunit) 611 { 612 si_info_t *sii; 613 uint found; 614 uint i; 615 616 sii = SI_INFO(sih); 617 618 found = 0; 619 620 for (i = 0; i < sii->numcores; i++) 621 if (sii->common_info->coreid[i] == coreid) { 622 if (found == coreunit) 623 return (i); 624 found++; 625 } 626 627 return (BADIDX); 628 } 629 630 /* return list of found cores */ 631 uint 632 si_corelist(si_t *sih, uint coreid[]) 633 { 634 si_info_t *sii; 635 636 sii = SI_INFO(sih); 637 638 bcopy((uchar*)sii->common_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); 639 return (sii->numcores); 640 } 641 642 /* return current register mapping */ 643 void * 644 si_coreregs(si_t *sih) 645 { 646 si_info_t *sii; 647 648 sii = SI_INFO(sih); 649 ASSERT(GOODREGS(sii->curmap)); 650 651 return (sii->curmap); 652 } 653 654 /* 655 * This function changes logical "focus" to the indicated core; 656 * must be called with interrupts off. 657 * Moreover, callers should keep interrupts off during switching out of and back to d11 core 658 */ 659 void * 660 si_setcore(si_t *sih, uint coreid, uint coreunit) 661 { 662 uint idx; 663 664 idx = si_findcoreidx(sih, coreid, coreunit); 665 if (!GOODIDX(idx)) 666 return (NULL); 667 668 if (CHIPTYPE(sih->socitype) == SOCI_SB) 669 return sb_setcoreidx(sih, idx); 670 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 671 return ai_setcoreidx(sih, idx); 672 else { 673 ASSERT(0); 674 return NULL; 675 } 676 } 677 678 void * 679 si_setcoreidx(si_t *sih, uint coreidx) 680 { 681 if (CHIPTYPE(sih->socitype) == SOCI_SB) 682 return sb_setcoreidx(sih, coreidx); 683 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 684 return ai_setcoreidx(sih, coreidx); 685 else { 686 ASSERT(0); 687 return NULL; 688 } 689 } 690 691 /* Turn off interrupt as required by sb_setcore, before switch core */ 692 void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) 693 { 694 void *cc; 695 si_info_t *sii; 696 697 sii = SI_INFO(sih); 698 699 INTR_OFF(sii, *intr_val); 700 *origidx = sii->curidx; 701 cc = si_setcore(sih, coreid, 0); 702 ASSERT(cc != NULL); 703 704 return cc; 705 } 706 707 /* restore coreidx and restore interrupt */ 708 void si_restore_core(si_t *sih, uint coreid, uint intr_val) 709 { 710 si_info_t *sii; 711 712 sii = SI_INFO(sih); 713 714 si_setcoreidx(sih, coreid); 715 INTR_RESTORE(sii, intr_val); 716 } 717 718 int 719 si_numaddrspaces(si_t *sih) 720 { 721 if (CHIPTYPE(sih->socitype) == SOCI_SB) 722 return sb_numaddrspaces(sih); 723 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 724 return ai_numaddrspaces(sih); 725 else { 726 ASSERT(0); 727 return 0; 728 } 729 } 730 731 uint32 732 si_addrspace(si_t *sih, uint asidx) 733 { 734 if (CHIPTYPE(sih->socitype) == SOCI_SB) 735 return sb_addrspace(sih, asidx); 736 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 737 return ai_addrspace(sih, asidx); 738 else { 739 ASSERT(0); 740 return 0; 741 } 742 } 743 744 uint32 745 si_addrspacesize(si_t *sih, uint asidx) 746 { 747 if (CHIPTYPE(sih->socitype) == SOCI_SB) 748 return sb_addrspacesize(sih, asidx); 749 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 750 return ai_addrspacesize(sih, asidx); 751 else { 752 ASSERT(0); 753 return 0; 754 } 755 } 756 757 uint32 758 si_core_cflags(si_t *sih, uint32 mask, uint32 val) 759 { 760 if (CHIPTYPE(sih->socitype) == SOCI_SB) 761 return sb_core_cflags(sih, mask, val); 762 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 763 return ai_core_cflags(sih, mask, val); 764 else { 765 ASSERT(0); 766 return 0; 767 } 768 } 769 770 void 771 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) 772 { 773 if (CHIPTYPE(sih->socitype) == SOCI_SB) 774 sb_core_cflags_wo(sih, mask, val); 775 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 776 ai_core_cflags_wo(sih, mask, val); 777 else 778 ASSERT(0); 779 } 780 781 uint32 782 si_core_sflags(si_t *sih, uint32 mask, uint32 val) 783 { 784 if (CHIPTYPE(sih->socitype) == SOCI_SB) 785 return sb_core_sflags(sih, mask, val); 786 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 787 return ai_core_sflags(sih, mask, val); 788 else { 789 ASSERT(0); 790 return 0; 791 } 792 } 793 794 bool 795 si_iscoreup(si_t *sih) 796 { 797 if (CHIPTYPE(sih->socitype) == SOCI_SB) 798 return sb_iscoreup(sih); 799 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 800 return ai_iscoreup(sih); 801 else { 802 ASSERT(0); 803 return FALSE; 804 } 805 } 806 807 void 808 si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val) 809 { 810 /* only for 4319, no requirement for SOCI_SB */ 811 if (CHIPTYPE(sih->socitype) == SOCI_AI) { 812 ai_write_wrap_reg(sih, offset, val); 813 } 814 else 815 return; 816 817 return; 818 } 819 820 uint 821 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 822 { 823 if (CHIPTYPE(sih->socitype) == SOCI_SB) 824 return sb_corereg(sih, coreidx, regoff, mask, val); 825 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 826 return ai_corereg(sih, coreidx, regoff, mask, val); 827 else { 828 ASSERT(0); 829 return 0; 830 } 831 } 832 833 void 834 si_core_disable(si_t *sih, uint32 bits) 835 { 836 if (CHIPTYPE(sih->socitype) == SOCI_SB) 837 sb_core_disable(sih, bits); 838 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 839 ai_core_disable(sih, bits); 840 } 841 842 void 843 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) 844 { 845 if (CHIPTYPE(sih->socitype) == SOCI_SB) 846 sb_core_reset(sih, bits, resetbits); 847 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 848 ai_core_reset(sih, bits, resetbits); 849 } 850 851 void 852 si_core_tofixup(si_t *sih) 853 { 854 if (CHIPTYPE(sih->socitype) == SOCI_SB) 855 sb_core_tofixup(sih); 856 } 857 858 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */ 859 int 860 si_corebist(si_t *sih) 861 { 862 uint32 cflags; 863 int result = 0; 864 865 /* Read core control flags */ 866 cflags = si_core_cflags(sih, 0, 0); 867 868 /* Set bist & fgc */ 869 si_core_cflags(sih, 0, (SICF_BIST_EN | SICF_FGC)); 870 871 /* Wait for bist done */ 872 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); 873 874 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) 875 result = BCME_ERROR; 876 877 /* Reset core control flags */ 878 si_core_cflags(sih, 0xffff, cflags); 879 880 return result; 881 } 882 883 static uint32 884 factor6(uint32 x) 885 { 886 switch (x) { 887 case CC_F6_2: return 2; 888 case CC_F6_3: return 3; 889 case CC_F6_4: return 4; 890 case CC_F6_5: return 5; 891 case CC_F6_6: return 6; 892 case CC_F6_7: return 7; 893 default: return 0; 894 } 895 } 896 897 /* calculate the speed the SI would run at given a set of clockcontrol values */ 898 uint32 899 si_clock_rate(uint32 pll_type, uint32 n, uint32 m) 900 { 901 uint32 n1, n2, clock, m1, m2, m3, mc; 902 903 n1 = n & CN_N1_MASK; 904 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; 905 906 if (pll_type == PLL_TYPE6) { 907 if (m & CC_T6_MMASK) 908 return CC_T6_M1; 909 else 910 return CC_T6_M0; 911 } else if ((pll_type == PLL_TYPE1) || 912 (pll_type == PLL_TYPE3) || 913 (pll_type == PLL_TYPE4) || 914 (pll_type == PLL_TYPE7)) { 915 n1 = factor6(n1); 916 n2 += CC_F5_BIAS; 917 } else if (pll_type == PLL_TYPE2) { 918 n1 += CC_T2_BIAS; 919 n2 += CC_T2_BIAS; 920 ASSERT((n1 >= 2) && (n1 <= 7)); 921 ASSERT((n2 >= 5) && (n2 <= 23)); 922 } else if (pll_type == PLL_TYPE5) { 923 return (100000000); 924 } else 925 ASSERT(0); 926 /* PLL types 3 and 7 use BASE2 (25Mhz) */ 927 if ((pll_type == PLL_TYPE3) || 928 (pll_type == PLL_TYPE7)) { 929 clock = CC_CLOCK_BASE2 * n1 * n2; 930 } else 931 clock = CC_CLOCK_BASE1 * n1 * n2; 932 933 if (clock == 0) 934 return 0; 935 936 m1 = m & CC_M1_MASK; 937 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; 938 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; 939 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; 940 941 if ((pll_type == PLL_TYPE1) || 942 (pll_type == PLL_TYPE3) || 943 (pll_type == PLL_TYPE4) || 944 (pll_type == PLL_TYPE7)) { 945 m1 = factor6(m1); 946 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) 947 m2 += CC_F5_BIAS; 948 else 949 m2 = factor6(m2); 950 m3 = factor6(m3); 951 952 switch (mc) { 953 case CC_MC_BYPASS: return (clock); 954 case CC_MC_M1: return (clock / m1); 955 case CC_MC_M1M2: return (clock / (m1 * m2)); 956 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); 957 case CC_MC_M1M3: return (clock / (m1 * m3)); 958 default: return (0); 959 } 960 } else { 961 ASSERT(pll_type == PLL_TYPE2); 962 963 m1 += CC_T2_BIAS; 964 m2 += CC_T2M2_BIAS; 965 m3 += CC_T2_BIAS; 966 ASSERT((m1 >= 2) && (m1 <= 7)); 967 ASSERT((m2 >= 3) && (m2 <= 10)); 968 ASSERT((m3 >= 2) && (m3 <= 7)); 969 970 if ((mc & CC_T2MC_M1BYP) == 0) 971 clock /= m1; 972 if ((mc & CC_T2MC_M2BYP) == 0) 973 clock /= m2; 974 if ((mc & CC_T2MC_M3BYP) == 0) 975 clock /= m3; 976 977 return (clock); 978 } 979 } 980 981 982 /* set chip watchdog reset timer to fire in 'ticks' */ 983 void 984 si_watchdog(si_t *sih, uint ticks) 985 { 986 if (PMUCTL_ENAB(sih)) { 987 988 if ((sih->chip == BCM4319_CHIP_ID) && (sih->chiprev == 0) && (ticks != 0)) { 989 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); 990 si_setcore(sih, USB20D_CORE_ID, 0); 991 si_core_disable(sih, 1); 992 si_setcore(sih, CC_CORE_ID, 0); 993 } 994 995 if (ticks == 1) 996 ticks = 2; 997 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); 998 } else { 999 /* instant NMI */ 1000 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); 1001 } 1002 } 1003 1004 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) 1005 /* trigger watchdog reset after ms milliseconds */ 1006 void 1007 si_watchdog_ms(si_t *sih, uint32 ms) 1008 { 1009 si_info_t *sii; 1010 1011 sii = SI_INFO(sih); 1012 1013 si_watchdog(sih, wd_msticks * ms); 1014 } 1015 #endif 1016 1017 1018 1019 /* initialize the sdio core */ 1020 void 1021 si_sdio_init(si_t *sih) 1022 { 1023 si_info_t *sii = SI_INFO(sih); 1024 1025 if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || 1026 (sih->buscoretype == SDIOD_CORE_ID)) { 1027 uint idx; 1028 sdpcmd_regs_t *sdpregs; 1029 1030 /* get the current core index */ 1031 idx = sii->curidx; 1032 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0)); 1033 1034 /* switch to sdio core */ 1035 if (!(sdpregs = (sdpcmd_regs_t *)si_setcore(sih, PCMCIA_CORE_ID, 0))) 1036 sdpregs = (sdpcmd_regs_t *)si_setcore(sih, SDIOD_CORE_ID, 0); 1037 ASSERT(sdpregs); 1038 1039 SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " 1040 "through SD core %d (%p)\n", 1041 sih->buscorerev, idx, sii->curidx, sdpregs)); 1042 1043 /* enable backplane error and core interrupts */ 1044 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT); 1045 W_REG(sii->osh, &sdpregs->sbintmask, (I_SB_SERR | I_SB_RESPERR | (1 << idx))); 1046 1047 /* switch back to previous core */ 1048 si_setcoreidx(sih, idx); 1049 } 1050 1051 /* enable interrupts */ 1052 bcmsdh_intr_enable(sii->sdh); 1053 1054 } 1055 1056 1057 /* change logical "focus" to the gpio core for optimized access */ 1058 void * 1059 si_gpiosetcore(si_t *sih) 1060 { 1061 return (si_setcoreidx(sih, SI_CC_IDX)); 1062 } 1063 1064 /* mask&set gpiocontrol bits */ 1065 uint32 1066 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1067 { 1068 uint regoff; 1069 1070 regoff = 0; 1071 1072 /* gpios could be shared on router platforms 1073 * ignore reservation if it's high priority (e.g., test apps) 1074 */ 1075 if ((priority != GPIO_HI_PRIORITY) && 1076 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1077 mask = priority ? (si_gpioreservation & mask) : 1078 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1079 val &= mask; 1080 } 1081 1082 regoff = OFFSETOF(chipcregs_t, gpiocontrol); 1083 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1084 } 1085 1086 /* mask&set gpio output enable bits */ 1087 uint32 1088 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1089 { 1090 uint regoff; 1091 1092 regoff = 0; 1093 1094 /* gpios could be shared on router platforms 1095 * ignore reservation if it's high priority (e.g., test apps) 1096 */ 1097 if ((priority != GPIO_HI_PRIORITY) && 1098 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1099 mask = priority ? (si_gpioreservation & mask) : 1100 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1101 val &= mask; 1102 } 1103 1104 regoff = OFFSETOF(chipcregs_t, gpioouten); 1105 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1106 } 1107 1108 /* mask&set gpio output bits */ 1109 uint32 1110 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1111 { 1112 uint regoff; 1113 1114 regoff = 0; 1115 1116 /* gpios could be shared on router platforms 1117 * ignore reservation if it's high priority (e.g., test apps) 1118 */ 1119 if ((priority != GPIO_HI_PRIORITY) && 1120 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1121 mask = priority ? (si_gpioreservation & mask) : 1122 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1123 val &= mask; 1124 } 1125 1126 regoff = OFFSETOF(chipcregs_t, gpioout); 1127 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1128 } 1129 1130 /* reserve one gpio */ 1131 uint32 1132 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1133 { 1134 si_info_t *sii; 1135 1136 sii = SI_INFO(sih); 1137 1138 /* only cores on SI_BUS share GPIO's and only applcation users need to 1139 * reserve/release GPIO 1140 */ 1141 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1142 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1143 return -1; 1144 } 1145 /* make sure only one bit is set */ 1146 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1147 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1148 return -1; 1149 } 1150 1151 /* already reserved */ 1152 if (si_gpioreservation & gpio_bitmask) 1153 return -1; 1154 /* set reservation */ 1155 si_gpioreservation |= gpio_bitmask; 1156 1157 return si_gpioreservation; 1158 } 1159 1160 /* release one gpio */ 1161 /* 1162 * releasing the gpio doesn't change the current value on the GPIO last write value 1163 * persists till some one overwrites it 1164 */ 1165 1166 uint32 1167 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1168 { 1169 si_info_t *sii; 1170 1171 sii = SI_INFO(sih); 1172 1173 /* only cores on SI_BUS share GPIO's and only applcation users need to 1174 * reserve/release GPIO 1175 */ 1176 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1177 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1178 return -1; 1179 } 1180 /* make sure only one bit is set */ 1181 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1182 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1183 return -1; 1184 } 1185 1186 /* already released */ 1187 if (!(si_gpioreservation & gpio_bitmask)) 1188 return -1; 1189 1190 /* clear reservation */ 1191 si_gpioreservation &= ~gpio_bitmask; 1192 1193 return si_gpioreservation; 1194 } 1195 1196 /* return the current gpioin register value */ 1197 uint32 1198 si_gpioin(si_t *sih) 1199 { 1200 si_info_t *sii; 1201 uint regoff; 1202 1203 sii = SI_INFO(sih); 1204 regoff = 0; 1205 1206 regoff = OFFSETOF(chipcregs_t, gpioin); 1207 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); 1208 } 1209 1210 /* mask&set gpio interrupt polarity bits */ 1211 uint32 1212 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1213 { 1214 si_info_t *sii; 1215 uint regoff; 1216 1217 sii = SI_INFO(sih); 1218 regoff = 0; 1219 1220 /* gpios could be shared on router platforms */ 1221 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1222 mask = priority ? (si_gpioreservation & mask) : 1223 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1224 val &= mask; 1225 } 1226 1227 regoff = OFFSETOF(chipcregs_t, gpiointpolarity); 1228 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1229 } 1230 1231 /* mask&set gpio interrupt mask bits */ 1232 uint32 1233 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1234 { 1235 si_info_t *sii; 1236 uint regoff; 1237 1238 sii = SI_INFO(sih); 1239 regoff = 0; 1240 1241 /* gpios could be shared on router platforms */ 1242 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1243 mask = priority ? (si_gpioreservation & mask) : 1244 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1245 val &= mask; 1246 } 1247 1248 regoff = OFFSETOF(chipcregs_t, gpiointmask); 1249 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1250 } 1251 1252 /* assign the gpio to an led */ 1253 uint32 1254 si_gpioled(si_t *sih, uint32 mask, uint32 val) 1255 { 1256 si_info_t *sii; 1257 1258 sii = SI_INFO(sih); 1259 if (sih->ccrev < 16) 1260 return -1; 1261 1262 /* gpio led powersave reg */ 1263 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); 1264 } 1265 1266 /* mask&set gpio timer val */ 1267 uint32 1268 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) 1269 { 1270 si_info_t *sii; 1271 1272 sii = SI_INFO(sih); 1273 1274 if (sih->ccrev < 16) 1275 return -1; 1276 1277 return (si_corereg(sih, SI_CC_IDX, 1278 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); 1279 } 1280 1281 uint32 1282 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) 1283 { 1284 si_info_t *sii; 1285 uint offs; 1286 1287 sii = SI_INFO(sih); 1288 if (sih->ccrev < 20) 1289 return -1; 1290 1291 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); 1292 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1293 } 1294 1295 uint32 1296 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) 1297 { 1298 si_info_t *sii; 1299 uint offs; 1300 1301 sii = SI_INFO(sih); 1302 if (sih->ccrev < 11) 1303 return -1; 1304 1305 if (regtype == GPIO_REGEVT) 1306 offs = OFFSETOF(chipcregs_t, gpioevent); 1307 else if (regtype == GPIO_REGEVT_INTMSK) 1308 offs = OFFSETOF(chipcregs_t, gpioeventintmask); 1309 else if (regtype == GPIO_REGEVT_INTPOL) 1310 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); 1311 else 1312 return -1; 1313 1314 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1315 } 1316 1317 void * 1318 si_gpio_handler_register(si_t *sih, uint32 event, 1319 bool level, gpio_handler_t cb, void *arg) 1320 { 1321 si_info_t *sii; 1322 gpioh_item_t *gi; 1323 1324 ASSERT(event); 1325 ASSERT(cb != NULL); 1326 1327 sii = SI_INFO(sih); 1328 if (sih->ccrev < 11) 1329 return NULL; 1330 1331 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) 1332 return NULL; 1333 1334 bzero(gi, sizeof(gpioh_item_t)); 1335 gi->event = event; 1336 gi->handler = cb; 1337 gi->arg = arg; 1338 gi->level = level; 1339 1340 gi->next = sii->gpioh_head; 1341 sii->gpioh_head = gi; 1342 1343 return (void *)(gi); 1344 } 1345 1346 void 1347 si_gpio_handler_unregister(si_t *sih, void *gpioh) 1348 { 1349 si_info_t *sii; 1350 gpioh_item_t *p, *n; 1351 1352 sii = SI_INFO(sih); 1353 if (sih->ccrev < 11) 1354 return; 1355 1356 ASSERT(sii->gpioh_head != NULL); 1357 if ((void*)sii->gpioh_head == gpioh) { 1358 sii->gpioh_head = sii->gpioh_head->next; 1359 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1360 return; 1361 } else { 1362 p = sii->gpioh_head; 1363 n = p->next; 1364 while (n) { 1365 if ((void*)n == gpioh) { 1366 p->next = n->next; 1367 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1368 return; 1369 } 1370 p = n; 1371 n = n->next; 1372 } 1373 } 1374 1375 ASSERT(0); /* Not found in list */ 1376 } 1377 1378 void 1379 si_gpio_handler_process(si_t *sih) 1380 { 1381 si_info_t *sii; 1382 gpioh_item_t *h; 1383 uint32 status; 1384 uint32 level = si_gpioin(sih); 1385 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); 1386 1387 sii = SI_INFO(sih); 1388 for (h = sii->gpioh_head; h != NULL; h = h->next) { 1389 if (h->handler) { 1390 status = (h->level ? level : edge); 1391 1392 if (status & h->event) 1393 h->handler(status, h->arg); 1394 } 1395 } 1396 1397 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ 1398 } 1399 1400 uint32 1401 si_gpio_int_enable(si_t *sih, bool enable) 1402 { 1403 si_info_t *sii; 1404 uint offs; 1405 1406 sii = SI_INFO(sih); 1407 if (sih->ccrev < 11) 1408 return -1; 1409 1410 offs = OFFSETOF(chipcregs_t, intmask); 1411 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); 1412 } 1413 1414 1415 /* Return the RAM size of the SOCRAM core */ 1416 uint32 1417 si_socram_size(si_t *sih) 1418 { 1419 si_info_t *sii; 1420 uint origidx; 1421 uint intr_val = 0; 1422 1423 sbsocramregs_t *regs; 1424 bool wasup; 1425 uint corerev; 1426 uint32 coreinfo; 1427 uint memsize = 0; 1428 1429 sii = SI_INFO(sih); 1430 1431 /* Block ints and save current core */ 1432 INTR_OFF(sii, intr_val); 1433 origidx = si_coreidx(sih); 1434 1435 /* Switch to SOCRAM core */ 1436 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1437 goto done; 1438 1439 /* Get info for determining size */ 1440 if (!(wasup = si_iscoreup(sih))) 1441 si_core_reset(sih, 0, 0); 1442 corerev = si_corerev(sih); 1443 coreinfo = R_REG(sii->osh, ®s->coreinfo); 1444 1445 /* Calculate size from coreinfo based on rev */ 1446 if (corerev == 0) 1447 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); 1448 else if (corerev < 3) { 1449 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); 1450 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1451 } else { 1452 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1453 uint bsz = (coreinfo & SRCI_SRBSZ_MASK); 1454 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 1455 if (lss != 0) 1456 nb --; 1457 memsize = nb * (1 << (bsz + SR_BSZ_BASE)); 1458 if (lss != 0) 1459 memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 1460 } 1461 1462 /* Return to previous state and core */ 1463 if (!wasup) 1464 si_core_disable(sih, 0); 1465 si_setcoreidx(sih, origidx); 1466 1467 done: 1468 INTR_RESTORE(sii, intr_val); 1469 1470 return memsize; 1471 } 1472 1473 1474 void 1475 si_btcgpiowar(si_t *sih) 1476 { 1477 si_info_t *sii; 1478 uint origidx; 1479 uint intr_val = 0; 1480 chipcregs_t *cc; 1481 1482 sii = SI_INFO(sih); 1483 1484 /* Make sure that there is ChipCommon core present && 1485 * UART_TX is strapped to 1 1486 */ 1487 if (!(sih->cccaps & CC_CAP_UARTGPIO)) 1488 return; 1489 1490 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ 1491 INTR_OFF(sii, intr_val); 1492 1493 origidx = si_coreidx(sih); 1494 1495 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 1496 ASSERT(cc != NULL); 1497 1498 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); 1499 1500 /* restore the original index */ 1501 si_setcoreidx(sih, origidx); 1502 1503 INTR_RESTORE(sii, intr_val); 1504 } 1505 1506 /* check if the device is removed */ 1507 bool 1508 si_deviceremoved(si_t *sih) 1509 { 1510 uint32 w; 1511 si_info_t *sii; 1512 1513 sii = SI_INFO(sih); 1514 1515 switch (BUSTYPE(sih->bustype)) { 1516 case PCI_BUS: 1517 ASSERT(sii->osh != NULL); 1518 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); 1519 if ((w & 0xFFFF) != VENDOR_BROADCOM) 1520 return TRUE; 1521 else 1522 return FALSE; 1523 default: 1524 return FALSE; 1525 } 1526 return FALSE; 1527 } 1528