/drivers/net/wireless/bcmdhd_29/siutils.c
C | 1915 lines | 1416 code | 320 blank | 179 comment | 508 complexity | 0a496f5b2db014c90a6f25eba2e494e8 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
1/* 2 * Misc utility routines for accessing chip-specific features 3 * of the SiliconBackplane-based Broadcom chips. 4 * 5 * Copyright (C) 1999-2011, 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.813.2.36 2011-02-10 23:43:55 $ 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 */ 50static 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); 52static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); 53static 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 */ 58static uint32 si_gpioreservation = 0; 59 60/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ 61 62/* 63 * Allocate a si handle. 64 * devid - pci device id (used to determine chip#) 65 * osh - opaque OS handle 66 * regs - virtual address of initial core registers 67 * bustype - pci/pcmcia/sb/sdio/etc 68 * vars - pointer to a pointer area for "environment" variables 69 * varsz - pointer to int to return the size of the vars 70 */ 71si_t * 72si_attach(uint devid, osl_t *osh, void *regs, 73 uint bustype, void *sdh, char **vars, uint *varsz) 74{ 75 si_info_t *sii; 76 77 /* alloc si_info_t */ 78 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { 79 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); 80 return (NULL); 81 } 82 83 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { 84 MFREE(osh, sii, sizeof(si_info_t)); 85 return (NULL); 86 } 87 sii->vars = vars ? *vars : NULL; 88 sii->varsz = varsz ? *varsz : 0; 89 90 return (si_t *)sii; 91} 92 93/* global kernel resource */ 94static si_info_t ksii; 95 96static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ 97 98/* generic kernel variant of si_attach() */ 99si_t * 100si_kattach(osl_t *osh) 101{ 102 static bool ksii_attached = FALSE; 103 104 if (!ksii_attached) { 105 void *regs; 106 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 107 108 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, 109 SI_BUS, NULL, 110 osh != SI_OSH ? &ksii.vars : NULL, 111 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { 112 SI_ERROR(("si_kattach: si_doattach failed\n")); 113 REG_UNMAP(regs); 114 return NULL; 115 } 116 REG_UNMAP(regs); 117 118 /* save ticks normalized to ms for si_watchdog_ms() */ 119 if (PMUCTL_ENAB(&ksii.pub)) { 120 /* based on 32KHz ILP clock */ 121 wd_msticks = 32; 122 } else { 123 wd_msticks = ALP_CLOCK / 1000; 124 } 125 126 ksii_attached = TRUE; 127 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", 128 ksii.pub.ccrev, wd_msticks)); 129 } 130 131 return &ksii.pub; 132} 133 134 135static bool 136si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) 137{ 138 /* need to set memseg flag for CF card first before any sb registers access */ 139 if (BUSTYPE(bustype) == PCMCIA_BUS) 140 sii->memseg = TRUE; 141 142 143 if (BUSTYPE(bustype) == SDIO_BUS) { 144 int err; 145 uint8 clkset; 146 147 /* Try forcing SDIO core to do ALPAvail request only */ 148 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; 149 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); 150 if (!err) { 151 uint8 clkval; 152 153 /* If register supported, wait for ALPAvail and then force ALP */ 154 clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL); 155 if ((clkval & ~SBSDIO_AVBITS) == clkset) { 156 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, 157 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), 158 PMU_MAX_TRANSITION_DLY); 159 if (!SBSDIO_ALPAV(clkval)) { 160 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", 161 clkval)); 162 return FALSE; 163 } 164 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; 165 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 166 clkset, &err); 167 OSL_DELAY(65); 168 } 169 } 170 171 /* Also, disable the extra SDIO pull-ups */ 172 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); 173 } 174 175 176 return TRUE; 177} 178 179static bool 180si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 181 uint *origidx, void *regs) 182{ 183 bool pci, pcie; 184 uint i; 185 uint pciidx, pcieidx, pcirev, pcierev; 186 187 cc = si_setcoreidx(&sii->pub, SI_CC_IDX); 188 ASSERT((uintptr)cc); 189 190 /* get chipcommon rev */ 191 sii->pub.ccrev = (int)si_corerev(&sii->pub); 192 193 /* get chipcommon chipstatus */ 194 if (sii->pub.ccrev >= 11) 195 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); 196 197 /* get chipcommon capabilites */ 198 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); 199 /* get chipcommon extended capabilities */ 200 201 if (sii->pub.ccrev >= 35) 202 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); 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 = (uint)NOREV; 217 sii->pub.buscoreidx = BADIDX; 218 219 pci = pcie = FALSE; 220 pcirev = pcierev = (uint)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_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", 232 i, cid, crev, sii->coresba[i], sii->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->coresba[i])) || 261 (regs == sii->regs[i])) 262 *origidx = i; 263 } 264 265 if (pci) { 266 sii->pub.buscoretype = PCI_CORE_ID; 267 sii->pub.buscorerev = pcirev; 268 sii->pub.buscoreidx = pciidx; 269 } else if (pcie) { 270 sii->pub.buscoretype = PCIE_CORE_ID; 271 sii->pub.buscorerev = pcierev; 272 sii->pub.buscoreidx = pcieidx; 273 } 274 275 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, 276 sii->pub.buscorerev)); 277 278 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && 279 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3)) 280 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); 281 282 283 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was 284 * already running. 285 */ 286 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { 287 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || 288 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) 289 si_core_disable(&sii->pub, 0); 290 } 291 292 /* return to the original core */ 293 si_setcoreidx(&sii->pub, *origidx); 294 295 return TRUE; 296} 297 298 299 300static si_info_t * 301si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 302 uint bustype, void *sdh, char **vars, uint *varsz) 303{ 304 struct si_pub *sih = &sii->pub; 305 uint32 w, savewin; 306 chipcregs_t *cc; 307 char *pvars = NULL; 308 uint origidx; 309 310 ASSERT(GOODREGS(regs)); 311 312 bzero((uchar*)sii, sizeof(si_info_t)); 313 314 savewin = 0; 315 316 sih->buscoreidx = BADIDX; 317 318 sii->curmap = regs; 319 sii->sdh = sdh; 320 sii->osh = osh; 321 322 323 324 /* find Chipcommon address */ 325 if (bustype == PCI_BUS) { 326 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 327 if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) 328 savewin = SI_ENUM_BASE; 329 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); 330 cc = (chipcregs_t *)regs; 331 } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { 332 cc = (chipcregs_t *)sii->curmap; 333 } else { 334 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 335 } 336 337 sih->bustype = bustype; 338 if (bustype != BUSTYPE(bustype)) { 339 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", 340 bustype, BUSTYPE(bustype))); 341 return NULL; 342 } 343 344 /* bus/core/clk setup for register access */ 345 if (!si_buscore_prep(sii, bustype, devid, sdh)) { 346 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); 347 return NULL; 348 } 349 350 /* ChipID recognition. 351 * We assume we can read chipid at offset 0 from the regs arg. 352 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), 353 * some way of recognizing them needs to be added here. 354 */ 355 w = R_REG(osh, &cc->chipid); 356 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 357 /* Might as wll fill in chip id rev & pkg */ 358 sih->chip = w & CID_ID_MASK; 359 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; 360 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; 361 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) 362 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | 363 CST4322_SPROM_PRESENT))) { 364 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__)); 365 return NULL; 366 } 367 368#if defined(HW_OOB) 369 if (CHIPID(sih->chip) == BCM43362_CHIP_ID) { 370 uint32 gpiocontrol, addr; 371 addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); 372 gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); 373 gpiocontrol |= 0x2; 374 bcmsdh_reg_write(sdh, addr, 4, gpiocontrol); 375 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL); 376 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL); 377 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL); 378 } 379#endif 380 381 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && 382 (sih->chippkg != BCM4329_289PIN_PKG_ID)) { 383 sih->chippkg = BCM4329_182PIN_PKG_ID; 384 } 385 386 sih->issim = IS_SIM(sih->chippkg); 387 388 /* scan for cores */ 389 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { 390 SI_MSG(("Found chip type SB (0x%08x)\n", w)); 391 sb_scan(&sii->pub, regs, devid); 392 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { 393 SI_MSG(("Found chip type AI (0x%08x)\n", w)); 394 /* pass chipc address instead of original core base */ 395 ai_scan(&sii->pub, (void *)(uintptr)cc, devid); 396 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { 397 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); 398 /* pass chipc address instead of original core base */ 399 ub_scan(&sii->pub, (void *)(uintptr)cc, devid); 400 } else { 401 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); 402 return NULL; 403 } 404 /* no cores found, bail out */ 405 if (sii->numcores == 0) { 406 SI_ERROR(("si_doattach: could not find any cores\n")); 407 return NULL; 408 } 409 /* bus/core/clk setup */ 410 origidx = SI_CC_IDX; 411 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { 412 SI_ERROR(("si_doattach: si_buscore_setup failed\n")); 413 goto exit; 414 } 415 416 /* assume current core is CC */ 417 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43234_CHIP_ID || 418 CHIPID(sih->chip) == BCM43235_CHIP_ID || 419 CHIPID(sih->chip) == BCM43236_CHIP_ID || 420 CHIPID(sih->chip) == BCM43238_CHIP_ID) && 421 (CHIPREV(sii->pub.chiprev) == 0))) { 422 423 if ((cc->chipstatus & CST43236_BP_CLK) != 0) { 424 uint clkdiv; 425 clkdiv = R_REG(osh, &cc->clkdiv); 426 /* otp_clk_div is even number, 120/14 < 9mhz */ 427 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT); 428 W_REG(osh, &cc->clkdiv, clkdiv); 429 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); 430 } 431 OSL_DELAY(10); 432 } 433 434 435 pvars = NULL; 436 437 438 439 if (sii->pub.ccrev >= 20) { 440 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 441 ASSERT(cc != NULL); 442 W_REG(osh, &cc->gpiopullup, 0); 443 W_REG(osh, &cc->gpiopulldown, 0); 444 si_setcoreidx(sih, origidx); 445 } 446 447 448 449 450 return (sii); 451 452exit: 453 454 return NULL; 455} 456 457/* may be called with core in reset */ 458void 459si_detach(si_t *sih) 460{ 461 si_info_t *sii; 462 uint idx; 463 464 465 sii = SI_INFO(sih); 466 467 if (sii == NULL) 468 return; 469 470 if (BUSTYPE(sih->bustype) == SI_BUS) 471 for (idx = 0; idx < SI_MAXCORES; idx++) 472 if (sii->regs[idx]) { 473 REG_UNMAP(sii->regs[idx]); 474 sii->regs[idx] = NULL; 475 } 476 477 478 479#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) 480 if (sii != &ksii) 481#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ 482 MFREE(sii->osh, sii, sizeof(si_info_t)); 483} 484 485void * 486si_osh(si_t *sih) 487{ 488 si_info_t *sii; 489 490 sii = SI_INFO(sih); 491 return sii->osh; 492} 493 494void 495si_setosh(si_t *sih, osl_t *osh) 496{ 497 si_info_t *sii; 498 499 sii = SI_INFO(sih); 500 if (sii->osh != NULL) { 501 SI_ERROR(("osh is already set....\n")); 502 ASSERT(!sii->osh); 503 } 504 sii->osh = osh; 505} 506 507/* register driver interrupt disabling and restoring callback functions */ 508void 509si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, 510 void *intrsenabled_fn, void *intr_arg) 511{ 512 si_info_t *sii; 513 514 sii = SI_INFO(sih); 515 sii->intr_arg = intr_arg; 516 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; 517 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; 518 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; 519 /* save current core id. when this function called, the current core 520 * must be the core which provides driver functions(il, et, wl, etc.) 521 */ 522 sii->dev_coreid = sii->coreid[sii->curidx]; 523} 524 525void 526si_deregister_intr_callback(si_t *sih) 527{ 528 si_info_t *sii; 529 530 sii = SI_INFO(sih); 531 sii->intrsoff_fn = NULL; 532} 533 534uint 535si_intflag(si_t *sih) 536{ 537 si_info_t *sii = SI_INFO(sih); 538 539 if (CHIPTYPE(sih->socitype) == SOCI_SB) 540 return sb_intflag(sih); 541 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 542 return R_REG(sii->osh, ((uint32 *)(uintptr) 543 (sii->oob_router + OOB_STATUSA))); 544 else { 545 ASSERT(0); 546 return 0; 547 } 548} 549 550uint 551si_flag(si_t *sih) 552{ 553 if (CHIPTYPE(sih->socitype) == SOCI_SB) 554 return sb_flag(sih); 555 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 556 return ai_flag(sih); 557 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 558 return ub_flag(sih); 559 else { 560 ASSERT(0); 561 return 0; 562 } 563} 564 565void 566si_setint(si_t *sih, int siflag) 567{ 568 if (CHIPTYPE(sih->socitype) == SOCI_SB) 569 sb_setint(sih, siflag); 570 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 571 ai_setint(sih, siflag); 572 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 573 ub_setint(sih, siflag); 574 else 575 ASSERT(0); 576} 577 578uint 579si_coreid(si_t *sih) 580{ 581 si_info_t *sii; 582 583 sii = SI_INFO(sih); 584 return sii->coreid[sii->curidx]; 585} 586 587uint 588si_coreidx(si_t *sih) 589{ 590 si_info_t *sii; 591 592 sii = SI_INFO(sih); 593 return sii->curidx; 594} 595 596/* return the core-type instantiation # of the current core */ 597uint 598si_coreunit(si_t *sih) 599{ 600 si_info_t *sii; 601 uint idx; 602 uint coreid; 603 uint coreunit; 604 uint i; 605 606 sii = SI_INFO(sih); 607 coreunit = 0; 608 609 idx = sii->curidx; 610 611 ASSERT(GOODREGS(sii->curmap)); 612 coreid = si_coreid(sih); 613 614 /* count the cores of our type */ 615 for (i = 0; i < idx; i++) 616 if (sii->coreid[i] == coreid) 617 coreunit++; 618 619 return (coreunit); 620} 621 622uint 623si_corevendor(si_t *sih) 624{ 625 if (CHIPTYPE(sih->socitype) == SOCI_SB) 626 return sb_corevendor(sih); 627 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 628 return ai_corevendor(sih); 629 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 630 return ub_corevendor(sih); 631 else { 632 ASSERT(0); 633 return 0; 634 } 635} 636 637bool 638si_backplane64(si_t *sih) 639{ 640 return ((sih->cccaps & CC_CAP_BKPLN64) != 0); 641} 642 643uint 644si_corerev(si_t *sih) 645{ 646 if (CHIPTYPE(sih->socitype) == SOCI_SB) 647 return sb_corerev(sih); 648 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 649 return ai_corerev(sih); 650 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 651 return ub_corerev(sih); 652 else { 653 ASSERT(0); 654 return 0; 655 } 656} 657 658/* return index of coreid or BADIDX if not found */ 659uint 660si_findcoreidx(si_t *sih, uint coreid, uint coreunit) 661{ 662 si_info_t *sii; 663 uint found; 664 uint i; 665 666 sii = SI_INFO(sih); 667 668 found = 0; 669 670 for (i = 0; i < sii->numcores; i++) 671 if (sii->coreid[i] == coreid) { 672 if (found == coreunit) 673 return (i); 674 found++; 675 } 676 677 return (BADIDX); 678} 679 680/* return list of found cores */ 681uint 682si_corelist(si_t *sih, uint coreid[]) 683{ 684 si_info_t *sii; 685 686 sii = SI_INFO(sih); 687 688 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); 689 return (sii->numcores); 690} 691 692/* return current register mapping */ 693void * 694si_coreregs(si_t *sih) 695{ 696 si_info_t *sii; 697 698 sii = SI_INFO(sih); 699 ASSERT(GOODREGS(sii->curmap)); 700 701 return (sii->curmap); 702} 703 704/* 705 * This function changes logical "focus" to the indicated core; 706 * must be called with interrupts off. 707 * Moreover, callers should keep interrupts off during switching out of and back to d11 core 708 */ 709void * 710si_setcore(si_t *sih, uint coreid, uint coreunit) 711{ 712 uint idx; 713 714 idx = si_findcoreidx(sih, coreid, coreunit); 715 if (!GOODIDX(idx)) 716 return (NULL); 717 718 if (CHIPTYPE(sih->socitype) == SOCI_SB) 719 return sb_setcoreidx(sih, idx); 720 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 721 return ai_setcoreidx(sih, idx); 722 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 723 return ub_setcoreidx(sih, idx); 724 else { 725 ASSERT(0); 726 return NULL; 727 } 728} 729 730void * 731si_setcoreidx(si_t *sih, uint coreidx) 732{ 733 if (CHIPTYPE(sih->socitype) == SOCI_SB) 734 return sb_setcoreidx(sih, coreidx); 735 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 736 return ai_setcoreidx(sih, coreidx); 737 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 738 return ub_setcoreidx(sih, coreidx); 739 else { 740 ASSERT(0); 741 return NULL; 742 } 743} 744 745/* Turn off interrupt as required by sb_setcore, before switch core */ 746void * 747si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) 748{ 749 void *cc; 750 si_info_t *sii; 751 752 sii = SI_INFO(sih); 753 754 if (SI_FAST(sii)) { 755 /* Overloading the origidx variable to remember the coreid, 756 * this works because the core ids cannot be confused with 757 * core indices. 758 */ 759 *origidx = coreid; 760 if (coreid == CC_CORE_ID) 761 return (void *)CCREGS_FAST(sii); 762 else if (coreid == sih->buscoretype) 763 return (void *)PCIEREGS(sii); 764 } 765 INTR_OFF(sii, *intr_val); 766 *origidx = sii->curidx; 767 cc = si_setcore(sih, coreid, 0); 768 ASSERT(cc != NULL); 769 770 return cc; 771} 772 773/* restore coreidx and restore interrupt */ 774void 775si_restore_core(si_t *sih, uint coreid, uint intr_val) 776{ 777 si_info_t *sii; 778 779 sii = SI_INFO(sih); 780 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) 781 return; 782 783 si_setcoreidx(sih, coreid); 784 INTR_RESTORE(sii, intr_val); 785} 786 787int 788si_numaddrspaces(si_t *sih) 789{ 790 if (CHIPTYPE(sih->socitype) == SOCI_SB) 791 return sb_numaddrspaces(sih); 792 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 793 return ai_numaddrspaces(sih); 794 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 795 return ub_numaddrspaces(sih); 796 else { 797 ASSERT(0); 798 return 0; 799 } 800} 801 802uint32 803si_addrspace(si_t *sih, uint asidx) 804{ 805 if (CHIPTYPE(sih->socitype) == SOCI_SB) 806 return sb_addrspace(sih, asidx); 807 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 808 return ai_addrspace(sih, asidx); 809 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 810 return ub_addrspace(sih, asidx); 811 else { 812 ASSERT(0); 813 return 0; 814 } 815} 816 817uint32 818si_addrspacesize(si_t *sih, uint asidx) 819{ 820 if (CHIPTYPE(sih->socitype) == SOCI_SB) 821 return sb_addrspacesize(sih, asidx); 822 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 823 return ai_addrspacesize(sih, asidx); 824 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 825 return ub_addrspacesize(sih, asidx); 826 else { 827 ASSERT(0); 828 return 0; 829 } 830} 831 832uint32 833si_core_cflags(si_t *sih, uint32 mask, uint32 val) 834{ 835 if (CHIPTYPE(sih->socitype) == SOCI_SB) 836 return sb_core_cflags(sih, mask, val); 837 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 838 return ai_core_cflags(sih, mask, val); 839 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 840 return ub_core_cflags(sih, mask, val); 841 else { 842 ASSERT(0); 843 return 0; 844 } 845} 846 847void 848si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) 849{ 850 if (CHIPTYPE(sih->socitype) == SOCI_SB) 851 sb_core_cflags_wo(sih, mask, val); 852 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 853 ai_core_cflags_wo(sih, mask, val); 854 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 855 ub_core_cflags_wo(sih, mask, val); 856 else 857 ASSERT(0); 858} 859 860uint32 861si_core_sflags(si_t *sih, uint32 mask, uint32 val) 862{ 863 if (CHIPTYPE(sih->socitype) == SOCI_SB) 864 return sb_core_sflags(sih, mask, val); 865 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 866 return ai_core_sflags(sih, mask, val); 867 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 868 return ub_core_sflags(sih, mask, val); 869 else { 870 ASSERT(0); 871 return 0; 872 } 873} 874 875bool 876si_iscoreup(si_t *sih) 877{ 878 if (CHIPTYPE(sih->socitype) == SOCI_SB) 879 return sb_iscoreup(sih); 880 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 881 return ai_iscoreup(sih); 882 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 883 return ub_iscoreup(sih); 884 else { 885 ASSERT(0); 886 return FALSE; 887 } 888} 889 890uint 891si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) 892{ 893 /* only for AI back plane chips */ 894 if (CHIPTYPE(sih->socitype) == SOCI_AI) 895 return (ai_wrap_reg(sih, offset, mask, val)); 896 return 0; 897} 898 899uint 900si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 901{ 902 if (CHIPTYPE(sih->socitype) == SOCI_SB) 903 return sb_corereg(sih, coreidx, regoff, mask, val); 904 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 905 return ai_corereg(sih, coreidx, regoff, mask, val); 906 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 907 return ub_corereg(sih, coreidx, regoff, mask, val); 908 else { 909 ASSERT(0); 910 return 0; 911 } 912} 913 914void 915si_core_disable(si_t *sih, uint32 bits) 916{ 917 if (CHIPTYPE(sih->socitype) == SOCI_SB) 918 sb_core_disable(sih, bits); 919 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 920 ai_core_disable(sih, bits); 921 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 922 ub_core_disable(sih, bits); 923} 924 925void 926si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) 927{ 928 if (CHIPTYPE(sih->socitype) == SOCI_SB) 929 sb_core_reset(sih, bits, resetbits); 930 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 931 ai_core_reset(sih, bits, resetbits); 932 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 933 ub_core_reset(sih, bits, resetbits); 934} 935 936/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ 937int 938si_corebist(si_t *sih) 939{ 940 uint32 cflags; 941 int result = 0; 942 943 /* Read core control flags */ 944 cflags = si_core_cflags(sih, 0, 0); 945 946 /* Set bist & fgc */ 947 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); 948 949 /* Wait for bist done */ 950 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); 951 952 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) 953 result = BCME_ERROR; 954 955 /* Reset core control flags */ 956 si_core_cflags(sih, 0xffff, cflags); 957 958 return result; 959} 960 961static uint32 962factor6(uint32 x) 963{ 964 switch (x) { 965 case CC_F6_2: return 2; 966 case CC_F6_3: return 3; 967 case CC_F6_4: return 4; 968 case CC_F6_5: return 5; 969 case CC_F6_6: return 6; 970 case CC_F6_7: return 7; 971 default: return 0; 972 } 973} 974 975/* calculate the speed the SI would run at given a set of clockcontrol values */ 976uint32 977si_clock_rate(uint32 pll_type, uint32 n, uint32 m) 978{ 979 uint32 n1, n2, clock, m1, m2, m3, mc; 980 981 n1 = n & CN_N1_MASK; 982 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; 983 984 if (pll_type == PLL_TYPE6) { 985 if (m & CC_T6_MMASK) 986 return CC_T6_M1; 987 else 988 return CC_T6_M0; 989 } else if ((pll_type == PLL_TYPE1) || 990 (pll_type == PLL_TYPE3) || 991 (pll_type == PLL_TYPE4) || 992 (pll_type == PLL_TYPE7)) { 993 n1 = factor6(n1); 994 n2 += CC_F5_BIAS; 995 } else if (pll_type == PLL_TYPE2) { 996 n1 += CC_T2_BIAS; 997 n2 += CC_T2_BIAS; 998 ASSERT((n1 >= 2) && (n1 <= 7)); 999 ASSERT((n2 >= 5) && (n2 <= 23)); 1000 } else if (pll_type == PLL_TYPE5) { 1001 return (100000000); 1002 } else 1003 ASSERT(0); 1004 /* PLL types 3 and 7 use BASE2 (25Mhz) */ 1005 if ((pll_type == PLL_TYPE3) || 1006 (pll_type == PLL_TYPE7)) { 1007 clock = CC_CLOCK_BASE2 * n1 * n2; 1008 } else 1009 clock = CC_CLOCK_BASE1 * n1 * n2; 1010 1011 if (clock == 0) 1012 return 0; 1013 1014 m1 = m & CC_M1_MASK; 1015 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; 1016 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; 1017 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; 1018 1019 if ((pll_type == PLL_TYPE1) || 1020 (pll_type == PLL_TYPE3) || 1021 (pll_type == PLL_TYPE4) || 1022 (pll_type == PLL_TYPE7)) { 1023 m1 = factor6(m1); 1024 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) 1025 m2 += CC_F5_BIAS; 1026 else 1027 m2 = factor6(m2); 1028 m3 = factor6(m3); 1029 1030 switch (mc) { 1031 case CC_MC_BYPASS: return (clock); 1032 case CC_MC_M1: return (clock / m1); 1033 case CC_MC_M1M2: return (clock / (m1 * m2)); 1034 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); 1035 case CC_MC_M1M3: return (clock / (m1 * m3)); 1036 default: return (0); 1037 } 1038 } else { 1039 ASSERT(pll_type == PLL_TYPE2); 1040 1041 m1 += CC_T2_BIAS; 1042 m2 += CC_T2M2_BIAS; 1043 m3 += CC_T2_BIAS; 1044 ASSERT((m1 >= 2) && (m1 <= 7)); 1045 ASSERT((m2 >= 3) && (m2 <= 10)); 1046 ASSERT((m3 >= 2) && (m3 <= 7)); 1047 1048 if ((mc & CC_T2MC_M1BYP) == 0) 1049 clock /= m1; 1050 if ((mc & CC_T2MC_M2BYP) == 0) 1051 clock /= m2; 1052 if ((mc & CC_T2MC_M3BYP) == 0) 1053 clock /= m3; 1054 1055 return (clock); 1056 } 1057} 1058 1059 1060/* set chip watchdog reset timer to fire in 'ticks' */ 1061void 1062si_watchdog(si_t *sih, uint ticks) 1063{ 1064 uint nb, maxt; 1065 1066 if (PMUCTL_ENAB(sih)) { 1067 1068 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && 1069 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { 1070 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); 1071 si_setcore(sih, USB20D_CORE_ID, 0); 1072 si_core_disable(sih, 1); 1073 si_setcore(sih, CC_CORE_ID, 0); 1074 } 1075 1076 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); 1077 /* The mips compiler uses the sllv instruction, 1078 * so we specially handle the 32-bit case. 1079 */ 1080 if (nb == 32) 1081 maxt = 0xffffffff; 1082 else 1083 maxt = ((1 << nb) - 1); 1084 1085 if (ticks == 1) 1086 ticks = 2; 1087 else if (ticks > maxt) 1088 ticks = maxt; 1089 1090 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); 1091 } else { 1092 maxt = (1 << 28) - 1; 1093 if (ticks > maxt) 1094 ticks = maxt; 1095 1096 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); 1097 } 1098} 1099 1100/* trigger watchdog reset after ms milliseconds */ 1101void 1102si_watchdog_ms(si_t *sih, uint32 ms) 1103{ 1104 si_watchdog(sih, wd_msticks * ms); 1105} 1106 1107 1108 1109 1110/* return the slow clock source - LPO, XTAL, or PCI */ 1111static uint 1112si_slowclk_src(si_info_t *sii) 1113{ 1114 chipcregs_t *cc; 1115 1116 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1117 1118 if (sii->pub.ccrev < 6) { 1119 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && 1120 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & 1121 PCI_CFG_GPIO_SCS)) 1122 return (SCC_SS_PCI); 1123 else 1124 return (SCC_SS_XTAL); 1125 } else if (sii->pub.ccrev < 10) { 1126 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); 1127 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); 1128 } else /* Insta-clock */ 1129 return (SCC_SS_XTAL); 1130} 1131 1132/* return the ILP (slowclock) min or max frequency */ 1133static uint 1134si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) 1135{ 1136 uint32 slowclk; 1137 uint div; 1138 1139 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1140 1141 /* shouldn't be here unless we've established the chip has dynamic clk control */ 1142 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); 1143 1144 slowclk = si_slowclk_src(sii); 1145 if (sii->pub.ccrev < 6) { 1146 if (slowclk == SCC_SS_PCI) 1147 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); 1148 else 1149 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); 1150 } else if (sii->pub.ccrev < 10) { 1151 div = 4 * 1152 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); 1153 if (slowclk == SCC_SS_LPO) 1154 return (max_freq ? LPOMAXFREQ : LPOMINFREQ); 1155 else if (slowclk == SCC_SS_XTAL) 1156 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); 1157 else if (slowclk == SCC_SS_PCI) 1158 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); 1159 else 1160 ASSERT(0); 1161 } else { 1162 /* Chipc rev 10 is InstaClock */ 1163 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; 1164 div = 4 * (div + 1); 1165 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); 1166 } 1167 return (0); 1168} 1169 1170static void 1171si_clkctl_setdelay(si_info_t *sii, void *chipcregs) 1172{ 1173 chipcregs_t *cc = (chipcregs_t *)chipcregs; 1174 uint slowmaxfreq, pll_delay, slowclk; 1175 uint pll_on_delay, fref_sel_delay; 1176 1177 pll_delay = PLL_DELAY; 1178 1179 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay 1180 * since the xtal will also be powered down by dynamic clk control logic. 1181 */ 1182 1183 slowclk = si_slowclk_src(sii); 1184 if (slowclk != SCC_SS_XTAL) 1185 pll_delay += XTAL_ON_DELAY; 1186 1187 /* Starting with 4318 it is ILP that is used for the delays */ 1188 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); 1189 1190 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; 1191 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; 1192 1193 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); 1194 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); 1195} 1196 1197/* initialize power control delay registers */ 1198void 1199si_clkctl_init(si_t *sih) 1200{ 1201 si_info_t *sii; 1202 uint origidx = 0; 1203 chipcregs_t *cc; 1204 bool fast; 1205 1206 if (!CCCTL_ENAB(sih)) 1207 return; 1208 1209 sii = SI_INFO(sih); 1210 fast = SI_FAST(sii); 1211 if (!fast) { 1212 origidx = sii->curidx; 1213 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 1214 return; 1215 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 1216 return; 1217 ASSERT(cc != NULL); 1218 1219 /* set all Instaclk chip ILP to 1 MHz */ 1220 if (sih->ccrev >= 10) 1221 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, 1222 (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); 1223 1224 si_clkctl_setdelay(sii, (void *)(uintptr)cc); 1225 1226 if (!fast) 1227 si_setcoreidx(sih, origidx); 1228} 1229 1230/* change logical "focus" to the gpio core for optimized access */ 1231void * 1232si_gpiosetcore(si_t *sih) 1233{ 1234 return (si_setcoreidx(sih, SI_CC_IDX)); 1235} 1236 1237/* mask&set gpiocontrol bits */ 1238uint32 1239si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1240{ 1241 uint regoff; 1242 1243 regoff = 0; 1244 1245 /* gpios could be shared on router platforms 1246 * ignore reservation if it's high priority (e.g., test apps) 1247 */ 1248 if ((priority != GPIO_HI_PRIORITY) && 1249 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1250 mask = priority ? (si_gpioreservation & mask) : 1251 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1252 val &= mask; 1253 } 1254 1255 regoff = OFFSETOF(chipcregs_t, gpiocontrol); 1256 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1257} 1258 1259/* mask&set gpio output enable bits */ 1260uint32 1261si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1262{ 1263 uint regoff; 1264 1265 regoff = 0; 1266 1267 /* gpios could be shared on router platforms 1268 * ignore reservation if it's high priority (e.g., test apps) 1269 */ 1270 if ((priority != GPIO_HI_PRIORITY) && 1271 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1272 mask = priority ? (si_gpioreservation & mask) : 1273 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1274 val &= mask; 1275 } 1276 1277 regoff = OFFSETOF(chipcregs_t, gpioouten); 1278 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1279} 1280 1281/* mask&set gpio output bits */ 1282uint32 1283si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1284{ 1285 uint regoff; 1286 1287 regoff = 0; 1288 1289 /* gpios could be shared on router platforms 1290 * ignore reservation if it's high priority (e.g., test apps) 1291 */ 1292 if ((priority != GPIO_HI_PRIORITY) && 1293 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1294 mask = priority ? (si_gpioreservation & mask) : 1295 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1296 val &= mask; 1297 } 1298 1299 regoff = OFFSETOF(chipcregs_t, gpioout); 1300 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1301} 1302 1303/* reserve one gpio */ 1304uint32 1305si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1306{ 1307 si_info_t *sii; 1308 1309 sii = SI_INFO(sih); 1310 1311 /* only cores on SI_BUS share GPIO's and only applcation users need to 1312 * reserve/release GPIO 1313 */ 1314 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1315 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1316 return 0xffffffff; 1317 } 1318 /* make sure only one bit is set */ 1319 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1320 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1321 return 0xffffffff; 1322 } 1323 1324 /* already reserved */ 1325 if (si_gpioreservation & gpio_bitmask) 1326 return 0xffffffff; 1327 /* set reservation */ 1328 si_gpioreservation |= gpio_bitmask; 1329 1330 return si_gpioreservation; 1331} 1332 1333/* release one gpio */ 1334/* 1335 * releasing the gpio doesn't change the current value on the GPIO last write value 1336 * persists till some one overwrites it 1337 */ 1338 1339uint32 1340si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1341{ 1342 si_info_t *sii; 1343 1344 sii = SI_INFO(sih); 1345 1346 /* only cores on SI_BUS share GPIO's and only applcation users need to 1347 * reserve/release GPIO 1348 */ 1349 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1350 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1351 return 0xffffffff; 1352 } 1353 /* make sure only one bit is set */ 1354 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1355 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1356 return 0xffffffff; 1357 } 1358 1359 /* already released */ 1360 if (!(si_gpioreservation & gpio_bitmask)) 1361 return 0xffffffff; 1362 1363 /* clear reservation */ 1364 si_gpioreservation &= ~gpio_bitmask; 1365 1366 return si_gpioreservation; 1367} 1368 1369/* return the current gpioin register value */ 1370uint32 1371si_gpioin(si_t *sih) 1372{ 1373 si_info_t *sii; 1374 uint regoff; 1375 1376 sii = SI_INFO(sih); 1377 regoff = 0; 1378 1379 regoff = OFFSETOF(chipcregs_t, gpioin); 1380 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); 1381} 1382 1383/* mask&set gpio interrupt polarity bits */ 1384uint32 1385si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1386{ 1387 si_info_t *sii; 1388 uint regoff; 1389 1390 sii = SI_INFO(sih); 1391 regoff = 0; 1392 1393 /* gpios could be shared on router platforms */ 1394 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1395 mask = priority ? (si_gpioreservation & mask) : 1396 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1397 val &= mask; 1398 } 1399 1400 regoff = OFFSETOF(chipcregs_t, gpiointpolarity); 1401 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1402} 1403 1404/* mask&set gpio interrupt mask bits */ 1405uint32 1406si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1407{ 1408 si_info_t *sii; 1409 uint regoff; 1410 1411 sii = SI_INFO(sih); 1412 regoff = 0; 1413 1414 /* gpios could be shared on router platforms */ 1415 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1416 mask = priority ? (si_gpioreservation & mask) : 1417 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1418 val &= mask; 1419 } 1420 1421 regoff = OFFSETOF(chipcregs_t, gpiointmask); 1422 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1423} 1424 1425/* assign the gpio to an led */ 1426uint32 1427si_gpioled(si_t *sih, uint32 mask, uint32 val) 1428{ 1429 si_info_t *sii; 1430 1431 sii = SI_INFO(sih); 1432 if (sih->ccrev < 16) 1433 return 0xffffffff; 1434 1435 /* gpio led powersave reg */ 1436 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); 1437} 1438 1439/* mask&set gpio timer val */ 1440uint32 1441si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) 1442{ 1443 si_info_t *sii; 1444 1445 sii = SI_INFO(sih); 1446 1447 if (sih->ccrev < 16) 1448 return 0xffffffff; 1449 1450 return (si_corereg(sih, SI_CC_IDX, 1451 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); 1452} 1453 1454uint32 1455si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) 1456{ 1457 si_info_t *sii; 1458 uint offs; 1459 1460 sii = SI_INFO(sih); 1461 if (sih->ccrev < 20) 1462 return 0xffffffff; 1463 1464 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); 1465 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1466} 1467 1468uint32 1469si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) 1470{ 1471 si_info_t *sii; 1472 uint offs; 1473 1474 sii = SI_INFO(sih); 1475 if (sih->ccrev < 11) 1476 return 0xffffffff; 1477 1478 if (regtype == GPIO_REGEVT) 1479 offs = OFFSETOF(chipcregs_t, gpioevent); 1480 else if (regtype == GPIO_REGEVT_INTMSK) 1481 offs = OFFSETOF(chipcregs_t, gpioeventintmask); 1482 else if (regtype == GPIO_REGEVT_INTPOL) 1483 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); 1484 else 1485 return 0xffffffff; 1486 1487 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1488} 1489 1490void * 1491si_gpio_handler_register(si_t *sih, uint32 event, 1492 bool level, gpio_handler_t cb, void *arg) 1493{ 1494 si_info_t *sii; 1495 gpioh_item_t *gi; 1496 1497 ASSERT(event); 1498 ASSERT(cb != NULL); 1499 1500 sii = SI_INFO(sih); 1501 if (sih->ccrev < 11) 1502 return NULL; 1503 1504 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) 1505 return NULL; 1506 1507 bzero(gi, sizeof(gpioh_item_t)); 1508 gi->event = event; 1509 gi->handler = cb; 1510 gi->arg = arg; 1511 gi->level = level; 1512 1513 gi->next = sii->gpioh_head; 1514 sii->gpioh_head = gi; 1515 1516 return (void *)(gi); 1517} 1518 1519void 1520si_gpio_handler_unregister(si_t *sih, void *gpioh) 1521{ 1522 si_info_t *sii; 1523 gpioh_item_t *p, *n; 1524 1525 sii = SI_INFO(sih); 1526 if (sih->ccrev < 11) 1527 return; 1528 1529 ASSERT(sii->gpioh_head != NULL); 1530 if ((void*)sii->gpioh_head == gpioh) { 1531 sii->gpioh_head = sii->gpioh_head->next; 1532 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1533 return; 1534 } else { 1535 p = sii->gpioh_head; 1536 n = p->next; 1537 while (n) { 1538 if ((void*)n == gpioh) { 1539 p->next = n->next; 1540 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1541 return; 1542 } 1543 p = n; 1544 n = n->next; 1545 } 1546 } 1547 1548 ASSERT(0); /* Not found in list */ 1549} 1550 1551void 1552si_gpio_handler_process(si_t *sih) 1553{ 1554 si_info_t *sii; 1555 gpioh_item_t *h; 1556 uint32 level = si_gpioin(sih); 1557 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0); 1558 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); 1559 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0); 1560 1561 sii = SI_INFO(sih); 1562 for (h = sii->gpioh_head; h != NULL; h = h->next) { 1563 if (h->handler) { 1564 uint32 status = (h->level ? level : edge) & h->event; 1565 uint32 polarity = (h->level ? levelp : edgep) & h->event; 1566 1567 /* polarity bitval is opposite of status bitval */ 1568 if (status ^ polarity) 1569 h->handler(status, h->arg); 1570 } 1571 } 1572 1573 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ 1574} 1575 1576uint32 1577si_gpio_int_enable(si_t *sih, bool enable) 1578{ 1579 si_info_t *sii; 1580 uint offs; 1581 1582 sii = SI_INFO(sih); 1583 if (sih->ccrev < 11) 1584 return 0xffffffff; 1585 1586 offs = OFFSETOF(chipcregs_t, intmask); 1587 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); 1588} 1589 1590 1591/* Return the size of the specified SOCRAM bank */ 1592static uint 1593socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type) 1594{ 1595 uint banksize, bankinfo; 1596 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1597 1598 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM); 1599 1600 W_REG(sii->osh, ®s->bankidx, bankidx); 1601 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1602 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1); 1603 return banksize; 1604} 1605 1606void 1607si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect) 1608{ 1609 si_info_t *sii; 1610 uint origidx; 1611 uint intr_val = 0; 1612 sbsocramregs_t *regs; 1613 bool wasup; 1614 uint corerev; 1615 1616 sii = SI_INFO(sih); 1617 1618 /* Block ints and save current core */ 1619 INTR_OFF(sii, intr_val); 1620 origidx = si_coreidx(sih); 1621 1622 if (!set) 1623 *enable = *protect = 0; 1624 1625 /* Switch to SOCRAM core */ 1626 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1627 goto done; 1628 1629 /* Get info for determining size */ 1630 if (!(wasup = si_iscoreup(sih))) 1631 si_core_reset(sih, 0, 0); 1632 1633 corerev = si_corerev(sih); 1634 if (corerev >= 10) { 1635 uint32 extcinfo; 1636 uint8 nb; 1637 uint8 i; 1638 uint32 bankidx, bankinfo; 1639 1640 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1641 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); 1642 for (i = 0; i < nb; i++) { 1643 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1644 W_REG(sii->osh, ®s->bankidx, bankidx); 1645 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1646 if (set) { 1647 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK; 1648 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK; 1649 if (*enable) { 1650 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT); 1651 if (*protect) 1652 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT); 1653 } 1654 W_REG(sii->osh, ®s->bankinfo, bankinfo); 1655 } 1656 else if (i == 0) { 1657 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) { 1658 *enable = 1; 1659 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK) 1660 *protect = 1; 1661 } 1662 } 1663 } 1664 } 1665 1666 /* Return to previous state and core */ 1667 if (!wasup) 1668 si_core_disable(sih, 0); 1669 si_setcoreidx(sih, origidx); 1670 1671done: 1672 INTR_RESTORE(sii, intr_val); 1673} 1674 1675bool 1676si_socdevram_pkg(si_t *sih) 1677{ 1678 if (si_socdevram_size(sih) > 0) 1679 return TRUE; 1680 else 1681 return FALSE; 1682} 1683 1684uint32 1685si_socdevram_size(si_t *sih) 1686{ 1687 si_info_t *sii; 1688 uint origidx; 1689 uint intr_val = 0; 1690 uint32 memsize = 0; 1691 sbsocramregs_t *regs; 1692 bool wasup; 1693 uint corerev; 1694 1695 sii = SI_INFO(sih); 1696 1697 /* Block ints and save current core */ 1698 INTR_OFF(sii, intr_val); 1699 origidx = si_coreidx(sih); 1700 1701 /* Switch to SOCRAM core */ 1702 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1703 goto done; 1704 1705 /* Get info for determining size */ 1706 if (!(wasup = si_iscoreup(sih))) 1707 si_core_reset(sih, 0, 0); 1708 1709 corerev = si_corerev(sih); 1710 if (corerev >= 10) { 1711 uint32 extcinfo; 1712 uint8 nb; 1713 uint8 i; 1714 1715 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1716 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); 1717 for (i = 0; i < nb; i++) 1718 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); 1719 } 1720 1721 /* Return to previous state and core */ 1722 if (!wasup) 1723 si_core_disable(sih, 0); 1724 si_setcoreidx(sih, origidx); 1725 1726done: 1727 INTR_RESTORE(sii, intr_val); 1728 1729 return memsize; 1730} 1731 1732/* Return the RAM size of the SOCRAM core */ 1733uint32 1734si_socram_size(si_t *sih) 1735{ 1736 si_info_t *sii; 1737 uint origidx; 1738 uint intr_val = 0; 1739 1740 sbsocramregs_t *regs; 1741 bool wasup; 1742 uint corerev; 1743 uint32 coreinfo; 1744 uint memsize = 0; 1745 1746 sii = SI_INFO(sih); 1747 1748 /* Block ints and save current core */ 1749 INTR_OFF(sii, intr_val); 1750 origidx = si_coreidx(sih); 1751 1752 /* Switch to SOCRAM core */ 1753 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1754 goto done; 1755 1756 /* Get info for determining size */ 1757 if (!(wasup = si_iscoreup(sih))) 1758 si_core_reset(sih, 0, 0); 1759 corerev = si_corerev(sih); 1760 coreinfo = R_REG(sii->osh, ®s->coreinfo); 1761 1762 /* Calculate size from coreinfo based on rev */ 1763 if (corerev == 0) 1764 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); 1765 else if (corerev < 3) { 1766 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); 1767 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1768 } else if ((corerev <= 7) || (corerev == 12)) { 1769 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1770 uint bsz = (coreinfo & SRCI_SRBSZ_MASK); 1771 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 1772 if (lss != 0) 1773 nb --; 1774 memsize = nb * (1 << (bsz + SR_BSZ_BASE)); 1775 if (lss != 0) 1776 memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 1777 } else { 1778 uint8 i; 1779 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1780 for (i = 0; i < nb; i++) 1781 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); 1782 } 1783 1784 /* Return to previous state and core */ 1785 if (!wasup) 1786 si_core_disable(sih, 0); 1787 si_setcoreidx(sih, origidx); 1788 1789done: 1790 INTR_RESTORE(sii, intr_val); 1791 1792 return memsize; 1793} 1794 1795 1796void 1797si_btcgpiowar(si_t *sih) 1798{ 1799 si_info_t *sii; 1800 uint origidx; 1801 uint intr_val = 0; 1802 chipcregs_t *cc; 1803 1804 sii = SI_INFO(sih); 1805 1806 /* Make sure that there is ChipCommon core present && 1807 * UART_TX is strapped to 1 1808 */ 1809 if (!(sih->cccaps & CC_CAP_UARTGPIO)) 1810 return; 1811 1812 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ 1813 INTR_OFF(sii, intr_val); 1814 1815 origidx = si_coreidx(sih); 1816 1817 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 1818 ASSERT(cc != NULL); 1819 1820 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); 1821 1822 /* restore the original index */ 1823 si_setcoreidx(sih, origidx); 1824 1825 INTR_RESTORE(sii, intr_val); 1826} 1827 1828uint 1829si_pll_reset(si_t *sih) 1830{ 1831 uint err = 0; 1832 1833 return (err); 1834} 1835 1836/* check if the device is removed */ 1837bool 1838si_deviceremoved(si_t *sih) 1839{ 1840 uint32 w; 1841 si_info_t *sii; 1842 1843 sii = SI_INFO(sih); 1844 1845 switch (BUSTYPE(sih->bustype)) { 1846 case PCI_BUS: 1847 ASSERT(sii->osh != NULL); 1848 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); 1849 if ((w & 0xFFFF) != VENDOR_BROADCOM) 1850 return TRUE; 1851 break; 1852 } 1853 return FALSE; 1854} 1855 1856bool 1857si_is_sprom_available(si_t *sih) 1858{ 1859 if (sih->ccrev >= 31) { 1860 si_info_t *sii; 1861 uint origidx; 1862 chipcregs_t *cc; 1863 uint32 sromctrl; 1864 1865 if ((sih->cccaps & CC_CAP_SROM) == 0) 1866 return FALSE; 1867 1868 sii = SI_INFO(sih); 1869 origidx = sii->curidx; 1870 cc = si_setcoreidx(sih, SI_CC_IDX); 1871 sromctrl = R_REG(sii->osh, &cc->sromcontrol); 1872 si_setcoreidx(sih, origidx); 1873 return (sromctrl & SRC_PRESENT); 1874 } 1875 1876 switch (CHIPID(sih->chip)) { 1877 case BCM4312_CHIP_ID: 1878 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); 1879 case BCM4325_CHIP_ID: 1880 return (sih->chipst & CST4325_SPROM_SEL) != 0; 1881 case BCM4322_CHIP_ID: 1882 case BCM43221_CHIP_ID: 1883 case BCM43231_CHIP_ID: 1884 case BCM43222_CHIP_ID: 1885 case BCM43111_CHIP_ID: 1886 case BCM43112_CHIP_ID: 1887 case BCM4342_CHIP_ID: 1888 { 1889 uint32 spromotp; 1890 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> 1891 CST4322_SPROM_OTP_SEL_SHIFT; 1892 return (spromotp & CST4322_SPROM_PRESENT) != 0; 1893 } 1894 case BCM4329_CHIP_ID: 1895 return (sih->chipst & CST4329_SPROM_SEL) != 0; 1896 case BCM4315_CHIP_ID: 1897 return (sih->chipst & CST4315_SPROM_SEL) != 0; 1898 case BCM4319_CHIP_ID: 1899 return (sih->chipst & CST4319_SPROM_SEL) != 0; 1900 1901 case BCM4336_CHIP_ID: 1902 case BCM43362_CHIP_ID: 1903 return (sih->chipst & CST4336_SPROM_PRESENT) != 0; 1904 1905 case BCM4330_CHIP_ID: 1906 return (sih->chipst & CST4330_SPROM_PRESENT) != 0; 1907 case BCM4313_CHIP_ID: 1908 return (sih->chipst & CST4313_SPROM_PRESENT) != 0; 1909 case BCM43239_CHIP_ID: 1910 return ((sih->chipst & CST43239_SPROM_MASK) && 1911 !(sih->chipst & CST43239_SFLASH_MASK)); 1912 default: 1913 return TRUE; 1914 } 1915}