1/* 2 * Misc utility routines for accessing chip-specific features 3 * of the SiliconBackplane-based Broadcom chips. 4 * 5 * Copyright (C) 1999-2012, 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 309908 2012-01-21 00:14:29Z $ 26 */ 27 28#include <bcm_cfg.h> 29#include <typedefs.h> 30#include <bcmdefs.h> 31#include <osl.h> 32#include <bcmutils.h> 33#include <siutils.h> 34#include <bcmdevs.h> 35#include <hndsoc.h> 36#include <sbchipc.h> 37#include <pcicfg.h> 38#include <sbpcmcia.h> 39#include <sbsocram.h> 40#include <bcmsdh.h> 41#include <sdio.h> 42#include <sbsdio.h> 43#include <sbhnddma.h> 44#include <sbsdpcmdev.h> 45#include <bcmsdpcm.h> 46#include <hndpmu.h> 47 48#include "siutils_priv.h" 49 50/* local prototypes */ 51static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 52 uint bustype, void *sdh, char **vars, uint *varsz); 53static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); 54static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 55 uint *origidx, void *regs); 56 57 58 59/* global variable to indicate reservation/release of gpio's */ 60static uint32 si_gpioreservation = 0; 61 62/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ 63 64int do_4360_pcie2_war = 0; 65 66/* 67 * Allocate a si handle. 68 * devid - pci device id (used to determine chip#) 69 * osh - opaque OS handle 70 * regs - virtual address of initial core registers 71 * bustype - pci/pcmcia/sb/sdio/etc 72 * vars - pointer to a pointer area for "environment" variables 73 * varsz - pointer to int to return the size of the vars 74 */ 75si_t * 76si_attach(uint devid, osl_t *osh, void *regs, 77 uint bustype, void *sdh, char **vars, uint *varsz) 78{ 79 si_info_t *sii; 80 81 /* alloc si_info_t */ 82 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { 83 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); 84 return (NULL); 85 } 86 87 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { 88 MFREE(osh, sii, sizeof(si_info_t)); 89 return (NULL); 90 } 91 sii->vars = vars ? *vars : NULL; 92 sii->varsz = varsz ? *varsz : 0; 93 94 return (si_t *)sii; 95} 96 97/* global kernel resource */ 98static si_info_t ksii; 99 100static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ 101 102/* generic kernel variant of si_attach() */ 103si_t * 104si_kattach(osl_t *osh) 105{ 106 static bool ksii_attached = FALSE; 107 108 if (!ksii_attached) { 109 void *regs; 110 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 111 112 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, 113 SI_BUS, NULL, 114 osh != SI_OSH ? &ksii.vars : NULL, 115 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { 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 139static bool 140si_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 183static bool 184si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 185 uint *origidx, void *regs) 186{ 187 bool pci, pcie, pcie_gen2 = FALSE; 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 /* get chipcommon extended capabilities */ 204 205 if (sii->pub.ccrev >= 35) 206 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); 207 208 /* get pmu rev and caps */ 209 if (sii->pub.cccaps & CC_CAP_PMU) { 210 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); 211 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; 212 } 213 214 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", 215 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, 216 sii->pub.pmucaps)); 217 218 /* figure out bus/orignal core idx */ 219 sii->pub.buscoretype = NODEV_CORE_ID; 220 sii->pub.buscorerev = (uint)NOREV; 221 sii->pub.buscoreidx = BADIDX; 222 223 pci = pcie = FALSE; 224 pcirev = pcierev = (uint)NOREV; 225 pciidx = pcieidx = BADIDX; 226 227 for (i = 0; i < sii->numcores; i++) { 228 uint cid, crev; 229 230 si_setcoreidx(&sii->pub, i); 231 cid = si_coreid(&sii->pub); 232 crev = si_corerev(&sii->pub); 233 234 /* Display cores found */ 235 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", 236 i, cid, crev, sii->coresba[i], sii->regs[i])); 237 238 if (BUSTYPE(bustype) == PCI_BUS) { 239 if (cid == PCI_CORE_ID) { 240 pciidx = i; 241 pcirev = crev; 242 pci = TRUE; 243 } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) { 244 pcieidx = i; 245 pcierev = crev; 246 pcie = TRUE; 247 if (cid == PCIE2_CORE_ID) 248 pcie_gen2 = TRUE; 249 } 250 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && 251 (cid == PCMCIA_CORE_ID)) { 252 sii->pub.buscorerev = crev; 253 sii->pub.buscoretype = cid; 254 sii->pub.buscoreidx = i; 255 } 256 else if (((BUSTYPE(bustype) == SDIO_BUS) || 257 (BUSTYPE(bustype) == SPI_BUS)) && 258 ((cid == PCMCIA_CORE_ID) || 259 (cid == SDIOD_CORE_ID))) { 260 sii->pub.buscorerev = crev; 261 sii->pub.buscoretype = cid; 262 sii->pub.buscoreidx = i; 263 } 264 265 /* find the core idx before entering this func. */ 266 if ((savewin && (savewin == sii->coresba[i])) || 267 (regs == sii->regs[i])) 268 *origidx = i; 269 } 270 271 if (pci) { 272 sii->pub.buscoretype = PCI_CORE_ID; 273 sii->pub.buscorerev = pcirev; 274 sii->pub.buscoreidx = pciidx; 275 } else if (pcie) { 276 if (pcie_gen2) 277 sii->pub.buscoretype = PCIE2_CORE_ID; 278 else 279 sii->pub.buscoretype = PCIE_CORE_ID; 280 sii->pub.buscorerev = pcierev; 281 sii->pub.buscoreidx = pcieidx; 282 } 283 284 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, 285 sii->pub.buscorerev)); 286 287 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && 288 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3)) 289 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); 290 291 292 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was 293 * already running. 294 */ 295 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { 296 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || 297 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) 298 si_core_disable(&sii->pub, 0); 299 } 300 301 /* return to the original core */ 302 si_setcoreidx(&sii->pub, *origidx); 303 304 return TRUE; 305} 306 307 308 309 310static si_info_t * 311si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 312 uint bustype, void *sdh, char **vars, uint *varsz) 313{ 314 struct si_pub *sih = &sii->pub; 315 uint32 w, savewin; 316 chipcregs_t *cc; 317 char *pvars = NULL; 318 uint origidx; 319 320 ASSERT(GOODREGS(regs)); 321 322 bzero((uchar*)sii, sizeof(si_info_t)); 323 324 savewin = 0; 325 326 sih->buscoreidx = BADIDX; 327 328 sii->curmap = regs; 329 sii->sdh = sdh; 330 sii->osh = osh; 331 332 333 334 /* find Chipcommon address */ 335 if (bustype == PCI_BUS) { 336 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 337 if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) 338 savewin = SI_ENUM_BASE; 339 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); 340 if (!regs) 341 return NULL; 342 cc = (chipcregs_t *)regs; 343 } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { 344 cc = (chipcregs_t *)sii->curmap; 345 } else { 346 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 347 } 348 349 sih->bustype = bustype; 350 if (bustype != BUSTYPE(bustype)) { 351 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", 352 bustype, BUSTYPE(bustype))); 353 return NULL; 354 } 355 356 /* bus/core/clk setup for register access */ 357 if (!si_buscore_prep(sii, bustype, devid, sdh)) { 358 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); 359 return NULL; 360 } 361 362 /* ChipID recognition. 363 * We assume we can read chipid at offset 0 from the regs arg. 364 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), 365 * some way of recognizing them needs to be added here. 366 */ 367 if (!cc) { 368 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); 369 return NULL; 370 } 371 w = R_REG(osh, &cc->chipid); 372 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 373 /* Might as wll fill in chip id rev & pkg */ 374 sih->chip = w & CID_ID_MASK; 375 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; 376 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; 377 378 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && 379 (sih->chippkg != BCM4329_289PIN_PKG_ID)) { 380 sih->chippkg = BCM4329_182PIN_PKG_ID; 381 } 382 sih->issim = IS_SIM(sih->chippkg); 383 384 /* scan for cores */ 385 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { 386 SI_MSG(("Found chip type SB (0x%08x)\n", w)); 387 sb_scan(&sii->pub, regs, devid); 388 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { 389 SI_MSG(("Found chip type AI (0x%08x)\n", w)); 390 /* pass chipc address instead of original core base */ 391 ai_scan(&sii->pub, (void *)(uintptr)cc, devid); 392 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { 393 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); 394 /* pass chipc address instead of original core base */ 395 ub_scan(&sii->pub, (void *)(uintptr)cc, devid); 396 } else { 397 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); 398 return NULL; 399 } 400 /* no cores found, bail out */ 401 if (sii->numcores == 0) { 402 SI_ERROR(("si_doattach: could not find any cores\n")); 403 return NULL; 404 } 405 /* bus/core/clk setup */ 406 origidx = SI_CC_IDX; 407 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { 408 SI_ERROR(("si_doattach: si_buscore_setup failed\n")); 409 goto exit; 410 } 411 412 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) 413 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | 414 CST4322_SPROM_PRESENT))) { 415 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__)); 416 return NULL; 417 } 418 419 /* assume current core is CC */ 420 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || 421 CHIPID(sih->chip) == BCM43235_CHIP_ID || 422 CHIPID(sih->chip) == BCM43234_CHIP_ID || 423 CHIPID(sih->chip) == BCM43238_CHIP_ID) && 424 (CHIPREV(sii->pub.chiprev) <= 2))) { 425 426 if ((cc->chipstatus & CST43236_BP_CLK) != 0) { 427 uint clkdiv; 428 clkdiv = R_REG(osh, &cc->clkdiv); 429 /* otp_clk_div is even number, 120/14 < 9mhz */ 430 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT); 431 W_REG(osh, &cc->clkdiv, clkdiv); 432 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); 433 } 434 OSL_DELAY(10); 435 } 436 437 if (bustype == PCI_BUS) { 438 439 } 440 441 pvars = NULL; 442 BCM_REFERENCE(pvars); 443 444 445 446 if (sii->pub.ccrev >= 20) { 447 uint32 gpiopullup = 0, gpiopulldown = 0; 448 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 449 ASSERT(cc != NULL); 450 451 /* 4314/43142 has pin muxing, don't clear gpio bits */ 452 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || 453 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { 454 gpiopullup |= 0x402e0; 455 gpiopulldown |= 0x20500; 456 } 457 458 W_REG(osh, &cc->gpiopullup, gpiopullup); 459 W_REG(osh, &cc->gpiopulldown, gpiopulldown); 460 si_setcoreidx(sih, origidx); 461 } 462 463 464 /* clear any previous epidiag-induced target abort */ 465 ASSERT(!si_taclear(sih, FALSE)); 466 467 return (sii); 468 469exit: 470 471 return NULL; 472} 473 474/* may be called with core in reset */ 475void 476si_detach(si_t *sih) 477{ 478 si_info_t *sii; 479 uint idx; 480 481 482 sii = SI_INFO(sih); 483 484 if (sii == NULL) 485 return; 486 487 if (BUSTYPE(sih->bustype) == SI_BUS) 488 for (idx = 0; idx < SI_MAXCORES; idx++) 489 if (sii->regs[idx]) { 490 REG_UNMAP(sii->regs[idx]); 491 sii->regs[idx] = NULL; 492 } 493 494 495 496#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) 497 if (sii != &ksii) 498#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ 499 MFREE(sii->osh, sii, sizeof(si_info_t)); 500} 501 502void * 503si_osh(si_t *sih) 504{ 505 si_info_t *sii; 506 507 sii = SI_INFO(sih); 508 return sii->osh; 509} 510 511void 512si_setosh(si_t *sih, osl_t *osh) 513{ 514 si_info_t *sii; 515 516 sii = SI_INFO(sih); 517 if (sii->osh != NULL) { 518 SI_ERROR(("osh is already set....\n")); 519 ASSERT(!sii->osh); 520 } 521 sii->osh = osh; 522} 523 524/* register driver interrupt disabling and restoring callback functions */ 525void 526si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, 527 void *intrsenabled_fn, void *intr_arg) 528{ 529 si_info_t *sii; 530 531 sii = SI_INFO(sih); 532 sii->intr_arg = intr_arg; 533 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; 534 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; 535 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; 536 /* save current core id. when this function called, the current core 537 * must be the core which provides driver functions(il, et, wl, etc.) 538 */ 539 sii->dev_coreid = sii->coreid[sii->curidx]; 540} 541 542void 543si_deregister_intr_callback(si_t *sih) 544{ 545 si_info_t *sii; 546 547 sii = SI_INFO(sih); 548 sii->intrsoff_fn = NULL; 549} 550 551uint 552si_intflag(si_t *sih) 553{ 554 si_info_t *sii = SI_INFO(sih); 555 556 if (CHIPTYPE(sih->socitype) == SOCI_SB) 557 return sb_intflag(sih); 558 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 559 return R_REG(sii->osh, ((uint32 *)(uintptr) 560 (sii->oob_router + OOB_STATUSA))); 561 else { 562 ASSERT(0); 563 return 0; 564 } 565} 566 567uint 568si_flag(si_t *sih) 569{ 570 if (CHIPTYPE(sih->socitype) == SOCI_SB) 571 return sb_flag(sih); 572 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 573 return ai_flag(sih); 574 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 575 return ub_flag(sih); 576 else { 577 ASSERT(0); 578 return 0; 579 } 580} 581 582void 583si_setint(si_t *sih, int siflag) 584{ 585 if (CHIPTYPE(sih->socitype) == SOCI_SB) 586 sb_setint(sih, siflag); 587 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 588 ai_setint(sih, siflag); 589 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 590 ub_setint(sih, siflag); 591 else 592 ASSERT(0); 593} 594 595uint 596si_coreid(si_t *sih) 597{ 598 si_info_t *sii; 599 600 sii = SI_INFO(sih); 601 return sii->coreid[sii->curidx]; 602} 603 604uint 605si_coreidx(si_t *sih) 606{ 607 si_info_t *sii; 608 609 sii = SI_INFO(sih); 610 return sii->curidx; 611} 612 613/* return the core-type instantiation # of the current core */ 614uint 615si_coreunit(si_t *sih) 616{ 617 si_info_t *sii; 618 uint idx; 619 uint coreid; 620 uint coreunit; 621 uint i; 622 623 sii = SI_INFO(sih); 624 coreunit = 0; 625 626 idx = sii->curidx; 627 628 ASSERT(GOODREGS(sii->curmap)); 629 coreid = si_coreid(sih); 630 631 /* count the cores of our type */ 632 for (i = 0; i < idx; i++) 633 if (sii->coreid[i] == coreid) 634 coreunit++; 635 636 return (coreunit); 637} 638 639uint 640si_corevendor(si_t *sih) 641{ 642 if (CHIPTYPE(sih->socitype) == SOCI_SB) 643 return sb_corevendor(sih); 644 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 645 return ai_corevendor(sih); 646 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 647 return ub_corevendor(sih); 648 else { 649 ASSERT(0); 650 return 0; 651 } 652} 653 654bool 655si_backplane64(si_t *sih) 656{ 657 return ((sih->cccaps & CC_CAP_BKPLN64) != 0); 658} 659 660uint 661si_corerev(si_t *sih) 662{ 663 if (CHIPTYPE(sih->socitype) == SOCI_SB) 664 return sb_corerev(sih); 665 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 666 return ai_corerev(sih); 667 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 668 return ub_corerev(sih); 669 else { 670 ASSERT(0); 671 return 0; 672 } 673} 674 675/* return index of coreid or BADIDX if not found */ 676uint 677si_findcoreidx(si_t *sih, uint coreid, uint coreunit) 678{ 679 si_info_t *sii; 680 uint found; 681 uint i; 682 683 sii = SI_INFO(sih); 684 685 found = 0; 686 687 for (i = 0; i < sii->numcores; i++) 688 if (sii->coreid[i] == coreid) { 689 if (found == coreunit) 690 return (i); 691 found++; 692 } 693 694 return (BADIDX); 695} 696 697/* return list of found cores */ 698uint 699si_corelist(si_t *sih, uint coreid[]) 700{ 701 si_info_t *sii; 702 703 sii = SI_INFO(sih); 704 705 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); 706 return (sii->numcores); 707} 708 709/* return current register mapping */ 710void * 711si_coreregs(si_t *sih) 712{ 713 si_info_t *sii; 714 715 sii = SI_INFO(sih); 716 ASSERT(GOODREGS(sii->curmap)); 717 718 return (sii->curmap); 719} 720 721/* 722 * This function changes logical "focus" to the indicated core; 723 * must be called with interrupts off. 724 * Moreover, callers should keep interrupts off during switching out of and back to d11 core 725 */ 726void * 727si_setcore(si_t *sih, uint coreid, uint coreunit) 728{ 729 uint idx; 730 731 idx = si_findcoreidx(sih, coreid, coreunit); 732 if (!GOODIDX(idx)) 733 return (NULL); 734 735 if (CHIPTYPE(sih->socitype) == SOCI_SB) 736 return sb_setcoreidx(sih, idx); 737 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 738 return ai_setcoreidx(sih, idx); 739 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 740 return ub_setcoreidx(sih, idx); 741 else { 742 ASSERT(0); 743 return NULL; 744 } 745} 746 747void * 748si_setcoreidx(si_t *sih, uint coreidx) 749{ 750 if (CHIPTYPE(sih->socitype) == SOCI_SB) 751 return sb_setcoreidx(sih, coreidx); 752 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 753 return ai_setcoreidx(sih, coreidx); 754 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 755 return ub_setcoreidx(sih, coreidx); 756 else { 757 ASSERT(0); 758 return NULL; 759 } 760} 761 762/* Turn off interrupt as required by sb_setcore, before switch core */ 763void * 764si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) 765{ 766 void *cc; 767 si_info_t *sii; 768 769 sii = SI_INFO(sih); 770 771 if (SI_FAST(sii)) { 772 /* Overloading the origidx variable to remember the coreid, 773 * this works because the core ids cannot be confused with 774 * core indices. 775 */ 776 *origidx = coreid; 777 if (coreid == CC_CORE_ID) 778 return (void *)CCREGS_FAST(sii); 779 else if (coreid == sih->buscoretype) 780 return (void *)PCIEREGS(sii); 781 } 782 INTR_OFF(sii, *intr_val); 783 *origidx = sii->curidx; 784 cc = si_setcore(sih, coreid, 0); 785 ASSERT(cc != NULL); 786 787 return cc; 788} 789 790/* restore coreidx and restore interrupt */ 791void 792si_restore_core(si_t *sih, uint coreid, uint intr_val) 793{ 794 si_info_t *sii; 795 796 sii = SI_INFO(sih); 797 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) 798 return; 799 800 si_setcoreidx(sih, coreid); 801 INTR_RESTORE(sii, intr_val); 802} 803 804int 805si_numaddrspaces(si_t *sih) 806{ 807 if (CHIPTYPE(sih->socitype) == SOCI_SB) 808 return sb_numaddrspaces(sih); 809 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 810 return ai_numaddrspaces(sih); 811 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 812 return ub_numaddrspaces(sih); 813 else { 814 ASSERT(0); 815 return 0; 816 } 817} 818 819uint32 820si_addrspace(si_t *sih, uint asidx) 821{ 822 if (CHIPTYPE(sih->socitype) == SOCI_SB) 823 return sb_addrspace(sih, asidx); 824 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 825 return ai_addrspace(sih, asidx); 826 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 827 return ub_addrspace(sih, asidx); 828 else { 829 ASSERT(0); 830 return 0; 831 } 832} 833 834uint32 835si_addrspacesize(si_t *sih, uint asidx) 836{ 837 if (CHIPTYPE(sih->socitype) == SOCI_SB) 838 return sb_addrspacesize(sih, asidx); 839 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 840 return ai_addrspacesize(sih, asidx); 841 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 842 return ub_addrspacesize(sih, asidx); 843 else { 844 ASSERT(0); 845 return 0; 846 } 847} 848 849void 850si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) 851{ 852 /* Only supported for SOCI_AI */ 853 if (CHIPTYPE(sih->socitype) == SOCI_AI) 854 ai_coreaddrspaceX(sih, asidx, addr, size); 855 else 856 *size = 0; 857} 858 859uint32 860si_core_cflags(si_t *sih, uint32 mask, uint32 val) 861{ 862 if (CHIPTYPE(sih->socitype) == SOCI_SB) 863 return sb_core_cflags(sih, mask, val); 864 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 865 return ai_core_cflags(sih, mask, val); 866 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 867 return ub_core_cflags(sih, mask, val); 868 else { 869 ASSERT(0); 870 return 0; 871 } 872} 873 874void 875si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) 876{ 877 if (CHIPTYPE(sih->socitype) == SOCI_SB) 878 sb_core_cflags_wo(sih, mask, val); 879 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 880 ai_core_cflags_wo(sih, mask, val); 881 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 882 ub_core_cflags_wo(sih, mask, val); 883 else 884 ASSERT(0); 885} 886 887uint32 888si_core_sflags(si_t *sih, uint32 mask, uint32 val) 889{ 890 if (CHIPTYPE(sih->socitype) == SOCI_SB) 891 return sb_core_sflags(sih, mask, val); 892 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 893 return ai_core_sflags(sih, mask, val); 894 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 895 return ub_core_sflags(sih, mask, val); 896 else { 897 ASSERT(0); 898 return 0; 899 } 900} 901 902bool 903si_iscoreup(si_t *sih) 904{ 905 if (CHIPTYPE(sih->socitype) == SOCI_SB) 906 return sb_iscoreup(sih); 907 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 908 return ai_iscoreup(sih); 909 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 910 return ub_iscoreup(sih); 911 else { 912 ASSERT(0); 913 return FALSE; 914 } 915} 916 917uint 918si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) 919{ 920 /* only for AI back plane chips */ 921 if (CHIPTYPE(sih->socitype) == SOCI_AI) 922 return (ai_wrap_reg(sih, offset, mask, val)); 923 return 0; 924} 925 926uint 927si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 928{ 929 if (CHIPTYPE(sih->socitype) == SOCI_SB) 930 return sb_corereg(sih, coreidx, regoff, mask, val); 931 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 932 return ai_corereg(sih, coreidx, regoff, mask, val); 933 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 934 return ub_corereg(sih, coreidx, regoff, mask, val); 935 else { 936 ASSERT(0); 937 return 0; 938 } 939} 940 941void 942si_core_disable(si_t *sih, uint32 bits) 943{ 944 if (CHIPTYPE(sih->socitype) == SOCI_SB) 945 sb_core_disable(sih, bits); 946 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 947 ai_core_disable(sih, bits); 948 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 949 ub_core_disable(sih, bits); 950} 951 952void 953si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) 954{ 955 if (CHIPTYPE(sih->socitype) == SOCI_SB) 956 sb_core_reset(sih, bits, resetbits); 957 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 958 ai_core_reset(sih, bits, resetbits); 959 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 960 ub_core_reset(sih, bits, resetbits); 961} 962 963/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ 964int 965si_corebist(si_t *sih) 966{ 967 uint32 cflags; 968 int result = 0; 969 970 /* Read core control flags */ 971 cflags = si_core_cflags(sih, 0, 0); 972 973 /* Set bist & fgc */ 974 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); 975 976 /* Wait for bist done */ 977 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); 978 979 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) 980 result = BCME_ERROR; 981 982 /* Reset core control flags */ 983 si_core_cflags(sih, 0xffff, cflags); 984 985 return result; 986} 987 988static uint32 989factor6(uint32 x) 990{ 991 switch (x) { 992 case CC_F6_2: return 2; 993 case CC_F6_3: return 3; 994 case CC_F6_4: return 4; 995 case CC_F6_5: return 5; 996 case CC_F6_6: return 6; 997 case CC_F6_7: return 7; 998 default: return 0; 999 } 1000} 1001 1002/* calculate the speed the SI would run at given a set of clockcontrol values */ 1003uint32 1004si_clock_rate(uint32 pll_type, uint32 n, uint32 m) 1005{ 1006 uint32 n1, n2, clock, m1, m2, m3, mc; 1007 1008 n1 = n & CN_N1_MASK; 1009 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; 1010 1011 if (pll_type == PLL_TYPE6) { 1012 if (m & CC_T6_MMASK) 1013 return CC_T6_M1; 1014 else 1015 return CC_T6_M0; 1016 } else if ((pll_type == PLL_TYPE1) || 1017 (pll_type == PLL_TYPE3) || 1018 (pll_type == PLL_TYPE4) || 1019 (pll_type == PLL_TYPE7)) { 1020 n1 = factor6(n1); 1021 n2 += CC_F5_BIAS; 1022 } else if (pll_type == PLL_TYPE2) { 1023 n1 += CC_T2_BIAS; 1024 n2 += CC_T2_BIAS; 1025 ASSERT((n1 >= 2) && (n1 <= 7)); 1026 ASSERT((n2 >= 5) && (n2 <= 23)); 1027 } else if (pll_type == PLL_TYPE5) { 1028 return (100000000); 1029 } else 1030 ASSERT(0); 1031 /* PLL types 3 and 7 use BASE2 (25Mhz) */ 1032 if ((pll_type == PLL_TYPE3) || 1033 (pll_type == PLL_TYPE7)) { 1034 clock = CC_CLOCK_BASE2 * n1 * n2; 1035 } else 1036 clock = CC_CLOCK_BASE1 * n1 * n2; 1037 1038 if (clock == 0) 1039 return 0; 1040 1041 m1 = m & CC_M1_MASK; 1042 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; 1043 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; 1044 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; 1045 1046 if ((pll_type == PLL_TYPE1) || 1047 (pll_type == PLL_TYPE3) || 1048 (pll_type == PLL_TYPE4) || 1049 (pll_type == PLL_TYPE7)) { 1050 m1 = factor6(m1); 1051 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) 1052 m2 += CC_F5_BIAS; 1053 else 1054 m2 = factor6(m2); 1055 m3 = factor6(m3); 1056 1057 switch (mc) { 1058 case CC_MC_BYPASS: return (clock); 1059 case CC_MC_M1: return (clock / m1); 1060 case CC_MC_M1M2: return (clock / (m1 * m2)); 1061 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); 1062 case CC_MC_M1M3: return (clock / (m1 * m3)); 1063 default: return (0); 1064 } 1065 } else { 1066 ASSERT(pll_type == PLL_TYPE2); 1067 1068 m1 += CC_T2_BIAS; 1069 m2 += CC_T2M2_BIAS; 1070 m3 += CC_T2_BIAS; 1071 ASSERT((m1 >= 2) && (m1 <= 7)); 1072 ASSERT((m2 >= 3) && (m2 <= 10)); 1073 ASSERT((m3 >= 2) && (m3 <= 7)); 1074 1075 if ((mc & CC_T2MC_M1BYP) == 0) 1076 clock /= m1; 1077 if ((mc & CC_T2MC_M2BYP) == 0) 1078 clock /= m2; 1079 if ((mc & CC_T2MC_M3BYP) == 0) 1080 clock /= m3; 1081 1082 return (clock); 1083 } 1084} 1085 1086 1087/* set chip watchdog reset timer to fire in 'ticks' */ 1088void 1089si_watchdog(si_t *sih, uint ticks) 1090{ 1091 uint nb, maxt; 1092 1093 if (PMUCTL_ENAB(sih)) { 1094 1095 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && 1096 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { 1097 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); 1098 si_setcore(sih, USB20D_CORE_ID, 0); 1099 si_core_disable(sih, 1); 1100 si_setcore(sih, CC_CORE_ID, 0); 1101 } 1102 1103 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); 1104 /* The mips compiler uses the sllv instruction, 1105 * so we specially handle the 32-bit case. 1106 */ 1107 if (nb == 32) 1108 maxt = 0xffffffff; 1109 else 1110 maxt = ((1 << nb) - 1); 1111 1112 if (ticks == 1) 1113 ticks = 2; 1114 else if (ticks > maxt) 1115 ticks = maxt; 1116 1117 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); 1118 } else { 1119 maxt = (1 << 28) - 1; 1120 if (ticks > maxt) 1121 ticks = maxt; 1122 1123 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); 1124 } 1125} 1126 1127/* trigger watchdog reset after ms milliseconds */ 1128void 1129si_watchdog_ms(si_t *sih, uint32 ms) 1130{ 1131 si_watchdog(sih, wd_msticks * ms); 1132} 1133 1134bool 1135si_taclear(si_t *sih, bool details) 1136{ 1137 return FALSE; 1138} 1139 1140 1141 1142/* return the slow clock source - LPO, XTAL, or PCI */ 1143static uint 1144si_slowclk_src(si_info_t *sii) 1145{ 1146 chipcregs_t *cc; 1147 1148 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1149 1150 if (sii->pub.ccrev < 6) { 1151 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && 1152 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & 1153 PCI_CFG_GPIO_SCS)) 1154 return (SCC_SS_PCI); 1155 else 1156 return (SCC_SS_XTAL); 1157 } else if (sii->pub.ccrev < 10) { 1158 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); 1159 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); 1160 } else /* Insta-clock */ 1161 return (SCC_SS_XTAL); 1162} 1163 1164/* return the ILP (slowclock) min or max frequency */ 1165static uint 1166si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) 1167{ 1168 uint32 slowclk; 1169 uint div; 1170 1171 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1172 1173 /* shouldn't be here unless we've established the chip has dynamic clk control */ 1174 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); 1175 1176 slowclk = si_slowclk_src(sii); 1177 if (sii->pub.ccrev < 6) { 1178 if (slowclk == SCC_SS_PCI) 1179 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); 1180 else 1181 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); 1182 } else if (sii->pub.ccrev < 10) { 1183 div = 4 * 1184 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); 1185 if (slowclk == SCC_SS_LPO) 1186 return (max_freq ? LPOMAXFREQ : LPOMINFREQ); 1187 else if (slowclk == SCC_SS_XTAL) 1188 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); 1189 else if (slowclk == SCC_SS_PCI) 1190 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); 1191 else 1192 ASSERT(0); 1193 } else { 1194 /* Chipc rev 10 is InstaClock */ 1195 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; 1196 div = 4 * (div + 1); 1197 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); 1198 } 1199 return (0); 1200} 1201 1202static void 1203si_clkctl_setdelay(si_info_t *sii, void *chipcregs) 1204{ 1205 chipcregs_t *cc = (chipcregs_t *)chipcregs; 1206 uint slowmaxfreq, pll_delay, slowclk; 1207 uint pll_on_delay, fref_sel_delay; 1208 1209 pll_delay = PLL_DELAY; 1210 1211 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay 1212 * since the xtal will also be powered down by dynamic clk control logic. 1213 */ 1214 1215 slowclk = si_slowclk_src(sii); 1216 if (slowclk != SCC_SS_XTAL) 1217 pll_delay += XTAL_ON_DELAY; 1218 1219 /* Starting with 4318 it is ILP that is used for the delays */ 1220 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); 1221 1222 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; 1223 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; 1224 1225 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); 1226 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); 1227} 1228 1229/* initialize power control delay registers */ 1230void 1231si_clkctl_init(si_t *sih) 1232{ 1233 si_info_t *sii; 1234 uint origidx = 0; 1235 chipcregs_t *cc; 1236 bool fast; 1237 1238 if (!CCCTL_ENAB(sih)) 1239 return; 1240 1241 sii = SI_INFO(sih); 1242 fast = SI_FAST(sii); 1243 if (!fast) { 1244 origidx = sii->curidx; 1245 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 1246 return; 1247 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 1248 return; 1249 ASSERT(cc != NULL); 1250 1251 /* set all Instaclk chip ILP to 1 MHz */ 1252 if (sih->ccrev >= 10) 1253 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, 1254 (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); 1255 1256 si_clkctl_setdelay(sii, (void *)(uintptr)cc); 1257 1258 if (!fast) 1259 si_setcoreidx(sih, origidx); 1260} 1261 1262 1263/* change logical "focus" to the gpio core for optimized access */ 1264void * 1265si_gpiosetcore(si_t *sih) 1266{ 1267 return (si_setcoreidx(sih, SI_CC_IDX)); 1268} 1269 1270/* 1271 * mask & set gpiocontrol bits. 1272 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin. 1273 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated 1274 * to some chip-specific purpose. 1275 */ 1276uint32 1277si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1278{ 1279 uint regoff; 1280 1281 regoff = 0; 1282 1283 /* gpios could be shared on router platforms 1284 * ignore reservation if it's high priority (e.g., test apps) 1285 */ 1286 if ((priority != GPIO_HI_PRIORITY) && 1287 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1288 mask = priority ? (si_gpioreservation & mask) : 1289 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1290 val &= mask; 1291 } 1292 1293 regoff = OFFSETOF(chipcregs_t, gpiocontrol); 1294 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1295} 1296 1297/* mask&set gpio output enable bits */ 1298uint32 1299si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1300{ 1301 uint regoff; 1302 1303 regoff = 0; 1304 1305 /* gpios could be shared on router platforms 1306 * ignore reservation if it's high priority (e.g., test apps) 1307 */ 1308 if ((priority != GPIO_HI_PRIORITY) && 1309 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1310 mask = priority ? (si_gpioreservation & mask) : 1311 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1312 val &= mask; 1313 } 1314 1315 regoff = OFFSETOF(chipcregs_t, gpioouten); 1316 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1317} 1318 1319/* mask&set gpio output bits */ 1320uint32 1321si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1322{ 1323 uint regoff; 1324 1325 regoff = 0; 1326 1327 /* gpios could be shared on router platforms 1328 * ignore reservation if it's high priority (e.g., test apps) 1329 */ 1330 if ((priority != GPIO_HI_PRIORITY) && 1331 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1332 mask = priority ? (si_gpioreservation & mask) : 1333 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1334 val &= mask; 1335 } 1336 1337 regoff = OFFSETOF(chipcregs_t, gpioout); 1338 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1339} 1340 1341/* reserve one gpio */ 1342uint32 1343si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1344{ 1345 /* only cores on SI_BUS share GPIO's and only applcation users need to 1346 * reserve/release GPIO 1347 */ 1348 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1349 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1350 return 0xffffffff; 1351 } 1352 /* make sure only one bit is set */ 1353 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1354 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1355 return 0xffffffff; 1356 } 1357 1358 /* already reserved */ 1359 if (si_gpioreservation & gpio_bitmask) 1360 return 0xffffffff; 1361 /* set reservation */ 1362 si_gpioreservation |= gpio_bitmask; 1363 1364 return si_gpioreservation; 1365} 1366 1367/* release one gpio */ 1368/* 1369 * releasing the gpio doesn't change the current value on the GPIO last write value 1370 * persists till some one overwrites it 1371 */ 1372 1373uint32 1374si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) 1375{ 1376 /* only cores on SI_BUS share GPIO's and only applcation users need to 1377 * reserve/release GPIO 1378 */ 1379 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 1380 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 1381 return 0xffffffff; 1382 } 1383 /* make sure only one bit is set */ 1384 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 1385 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 1386 return 0xffffffff; 1387 } 1388 1389 /* already released */ 1390 if (!(si_gpioreservation & gpio_bitmask)) 1391 return 0xffffffff; 1392 1393 /* clear reservation */ 1394 si_gpioreservation &= ~gpio_bitmask; 1395 1396 return si_gpioreservation; 1397} 1398 1399/* return the current gpioin register value */ 1400uint32 1401si_gpioin(si_t *sih) 1402{ 1403 uint regoff; 1404 1405 regoff = OFFSETOF(chipcregs_t, gpioin); 1406 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); 1407} 1408 1409/* mask&set gpio interrupt polarity bits */ 1410uint32 1411si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1412{ 1413 uint regoff; 1414 1415 /* gpios could be shared on router platforms */ 1416 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1417 mask = priority ? (si_gpioreservation & mask) : 1418 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1419 val &= mask; 1420 } 1421 1422 regoff = OFFSETOF(chipcregs_t, gpiointpolarity); 1423 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1424} 1425 1426/* mask&set gpio interrupt mask bits */ 1427uint32 1428si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) 1429{ 1430 uint regoff; 1431 1432 /* gpios could be shared on router platforms */ 1433 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 1434 mask = priority ? (si_gpioreservation & mask) : 1435 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 1436 val &= mask; 1437 } 1438 1439 regoff = OFFSETOF(chipcregs_t, gpiointmask); 1440 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 1441} 1442 1443/* assign the gpio to an led */ 1444uint32 1445si_gpioled(si_t *sih, uint32 mask, uint32 val) 1446{ 1447 if (sih->ccrev < 16) 1448 return 0xffffffff; 1449 1450 /* gpio led powersave reg */ 1451 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); 1452} 1453 1454/* mask&set gpio timer val */ 1455uint32 1456si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) 1457{ 1458 if (sih->ccrev < 16) 1459 return 0xffffffff; 1460 1461 return (si_corereg(sih, SI_CC_IDX, 1462 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); 1463} 1464 1465uint32 1466si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) 1467{ 1468 uint offs; 1469 1470 if (sih->ccrev < 20) 1471 return 0xffffffff; 1472 1473 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); 1474 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1475} 1476 1477uint32 1478si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) 1479{ 1480 uint offs; 1481 1482 if (sih->ccrev < 11) 1483 return 0xffffffff; 1484 1485 if (regtype == GPIO_REGEVT) 1486 offs = OFFSETOF(chipcregs_t, gpioevent); 1487 else if (regtype == GPIO_REGEVT_INTMSK) 1488 offs = OFFSETOF(chipcregs_t, gpioeventintmask); 1489 else if (regtype == GPIO_REGEVT_INTPOL) 1490 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); 1491 else 1492 return 0xffffffff; 1493 1494 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 1495} 1496 1497void * 1498si_gpio_handler_register(si_t *sih, uint32 event, 1499 bool level, gpio_handler_t cb, void *arg) 1500{ 1501 si_info_t *sii; 1502 gpioh_item_t *gi; 1503 1504 ASSERT(event); 1505 ASSERT(cb != NULL); 1506 1507 sii = SI_INFO(sih); 1508 if (sih->ccrev < 11) 1509 return NULL; 1510 1511 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) 1512 return NULL; 1513 1514 bzero(gi, sizeof(gpioh_item_t)); 1515 gi->event = event; 1516 gi->handler = cb; 1517 gi->arg = arg; 1518 gi->level = level; 1519 1520 gi->next = sii->gpioh_head; 1521 sii->gpioh_head = gi; 1522 1523 return (void *)(gi); 1524} 1525 1526void 1527si_gpio_handler_unregister(si_t *sih, void *gpioh) 1528{ 1529 si_info_t *sii; 1530 gpioh_item_t *p, *n; 1531 1532 sii = SI_INFO(sih); 1533 if (sih->ccrev < 11) 1534 return; 1535 1536 ASSERT(sii->gpioh_head != NULL); 1537 if ((void*)sii->gpioh_head == gpioh) { 1538 sii->gpioh_head = sii->gpioh_head->next; 1539 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1540 return; 1541 } else { 1542 p = sii->gpioh_head; 1543 n = p->next; 1544 while (n) { 1545 if ((void*)n == gpioh) { 1546 p->next = n->next; 1547 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 1548 return; 1549 } 1550 p = n; 1551 n = n->next; 1552 } 1553 } 1554 1555 ASSERT(0); /* Not found in list */ 1556} 1557 1558void 1559si_gpio_handler_process(si_t *sih) 1560{ 1561 si_info_t *sii; 1562 gpioh_item_t *h; 1563 uint32 level = si_gpioin(sih); 1564 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0); 1565 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); 1566 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0); 1567 1568 sii = SI_INFO(sih); 1569 for (h = sii->gpioh_head; h != NULL; h = h->next) { 1570 if (h->handler) { 1571 uint32 status = (h->level ? level : edge) & h->event; 1572 uint32 polarity = (h->level ? levelp : edgep) & h->event; 1573 1574 /* polarity bitval is opposite of status bitval */ 1575 if (status ^ polarity) 1576 h->handler(status, h->arg); 1577 } 1578 } 1579 1580 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ 1581} 1582 1583uint32 1584si_gpio_int_enable(si_t *sih, bool enable) 1585{ 1586 uint offs; 1587 1588 if (sih->ccrev < 11) 1589 return 0xffffffff; 1590 1591 offs = OFFSETOF(chipcregs_t, intmask); 1592 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); 1593} 1594 1595 1596/* Return the size of the specified SOCRAM bank */ 1597static uint 1598socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type) 1599{ 1600 uint banksize, bankinfo; 1601 uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1602 1603 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM); 1604 1605 W_REG(sii->osh, ®s->bankidx, bankidx); 1606 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1607 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1); 1608 return banksize; 1609} 1610 1611void 1612si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap) 1613{ 1614 si_info_t *sii; 1615 uint origidx; 1616 uint intr_val = 0; 1617 sbsocramregs_t *regs; 1618 bool wasup; 1619 uint corerev; 1620 1621 sii = SI_INFO(sih); 1622 1623 /* Block ints and save current core */ 1624 INTR_OFF(sii, intr_val); 1625 origidx = si_coreidx(sih); 1626 1627 if (!set) 1628 *enable = *protect = *remap = 0; 1629 1630 /* Switch to SOCRAM core */ 1631 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1632 goto done; 1633 1634 /* Get info for determining size */ 1635 if (!(wasup = si_iscoreup(sih))) 1636 si_core_reset(sih, 0, 0); 1637 1638 corerev = si_corerev(sih); 1639 if (corerev >= 10) { 1640 uint32 extcinfo; 1641 uint8 nb; 1642 uint8 i; 1643 uint32 bankidx, bankinfo; 1644 1645 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1646 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); 1647 for (i = 0; i < nb; i++) { 1648 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1649 W_REG(sii->osh, ®s->bankidx, bankidx); 1650 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1651 if (set) { 1652 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK; 1653 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK; 1654 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK; 1655 if (*enable) { 1656 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT); 1657 if (*protect) 1658 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT); 1659 if ((corerev >= 16) && *remap) 1660 bankinfo |= 1661 (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT); 1662 } 1663 W_REG(sii->osh, ®s->bankinfo, bankinfo); 1664 } 1665 else if (i == 0) { 1666 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) { 1667 *enable = 1; 1668 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK) 1669 *protect = 1; 1670 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) 1671 *remap = 1; 1672 } 1673 } 1674 } 1675 } 1676 1677 /* Return to previous state and core */ 1678 if (!wasup) 1679 si_core_disable(sih, 0); 1680 si_setcoreidx(sih, origidx); 1681 1682done: 1683 INTR_RESTORE(sii, intr_val); 1684} 1685 1686bool 1687si_socdevram_remap_isenb(si_t *sih) 1688{ 1689 si_info_t *sii; 1690 uint origidx; 1691 uint intr_val = 0; 1692 sbsocramregs_t *regs; 1693 bool wasup, remap = FALSE; 1694 uint corerev; 1695 uint32 extcinfo; 1696 uint8 nb; 1697 uint8 i; 1698 uint32 bankidx, bankinfo; 1699 1700 sii = SI_INFO(sih); 1701 1702 /* Block ints and save current core */ 1703 INTR_OFF(sii, intr_val); 1704 origidx = si_coreidx(sih); 1705 1706 /* Switch to SOCRAM core */ 1707 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1708 goto done; 1709 1710 /* Get info for determining size */ 1711 if (!(wasup = si_iscoreup(sih))) 1712 si_core_reset(sih, 0, 0); 1713 1714 corerev = si_corerev(sih); 1715 if (corerev >= 16) { 1716 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1717 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); 1718 for (i = 0; i < nb; i++) { 1719 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1720 W_REG(sii->osh, ®s->bankidx, bankidx); 1721 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1722 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) { 1723 remap = TRUE; 1724 break; 1725 } 1726 } 1727 } 1728 1729 /* Return to previous state and core */ 1730 if (!wasup) 1731 si_core_disable(sih, 0); 1732 si_setcoreidx(sih, origidx); 1733 1734done: 1735 INTR_RESTORE(sii, intr_val); 1736 return remap; 1737} 1738 1739bool 1740si_socdevram_pkg(si_t *sih) 1741{ 1742 if (si_socdevram_size(sih) > 0) 1743 return TRUE; 1744 else 1745 return FALSE; 1746} 1747 1748uint32 1749si_socdevram_size(si_t *sih) 1750{ 1751 si_info_t *sii; 1752 uint origidx; 1753 uint intr_val = 0; 1754 uint32 memsize = 0; 1755 sbsocramregs_t *regs; 1756 bool wasup; 1757 uint corerev; 1758 1759 sii = SI_INFO(sih); 1760 1761 /* Block ints and save current core */ 1762 INTR_OFF(sii, intr_val); 1763 origidx = si_coreidx(sih); 1764 1765 /* Switch to SOCRAM core */ 1766 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1767 goto done; 1768 1769 /* Get info for determining size */ 1770 if (!(wasup = si_iscoreup(sih))) 1771 si_core_reset(sih, 0, 0); 1772 1773 corerev = si_corerev(sih); 1774 if (corerev >= 10) { 1775 uint32 extcinfo; 1776 uint8 nb; 1777 uint8 i; 1778 1779 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1780 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); 1781 for (i = 0; i < nb; i++) 1782 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); 1783 } 1784 1785 /* Return to previous state and core */ 1786 if (!wasup) 1787 si_core_disable(sih, 0); 1788 si_setcoreidx(sih, origidx); 1789 1790done: 1791 INTR_RESTORE(sii, intr_val); 1792 1793 return memsize; 1794} 1795 1796uint32 1797si_socdevram_remap_size(si_t *sih) 1798{ 1799 si_info_t *sii; 1800 uint origidx; 1801 uint intr_val = 0; 1802 uint32 memsize = 0, banksz; 1803 sbsocramregs_t *regs; 1804 bool wasup; 1805 uint corerev; 1806 uint32 extcinfo; 1807 uint8 nb; 1808 uint8 i; 1809 uint32 bankidx, bankinfo; 1810 1811 sii = SI_INFO(sih); 1812 1813 /* Block ints and save current core */ 1814 INTR_OFF(sii, intr_val); 1815 origidx = si_coreidx(sih); 1816 1817 /* Switch to SOCRAM core */ 1818 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1819 goto done; 1820 1821 /* Get info for determining size */ 1822 if (!(wasup = si_iscoreup(sih))) 1823 si_core_reset(sih, 0, 0); 1824 1825 corerev = si_corerev(sih); 1826 if (corerev >= 16) { 1827 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 1828 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); 1829 1830 /* 1831 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB 1832 * Only four banks are accessible to ARM 1833 */ 1834 if ((corerev == 16) && (nb == 5)) 1835 nb = 4; 1836 1837 for (i = 0; i < nb; i++) { 1838 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 1839 W_REG(sii->osh, ®s->bankidx, bankidx); 1840 bankinfo = R_REG(sii->osh, ®s->bankinfo); 1841 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) { 1842 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); 1843 memsize += banksz; 1844 } else { 1845 /* Account only consecutive banks for now */ 1846 break; 1847 } 1848 } 1849 } 1850 1851 /* Return to previous state and core */ 1852 if (!wasup) 1853 si_core_disable(sih, 0); 1854 si_setcoreidx(sih, origidx); 1855 1856done: 1857 INTR_RESTORE(sii, intr_val); 1858 1859 return memsize; 1860} 1861 1862/* Return the RAM size of the SOCRAM core */ 1863uint32 1864si_socram_size(si_t *sih) 1865{ 1866 si_info_t *sii; 1867 uint origidx; 1868 uint intr_val = 0; 1869 1870 sbsocramregs_t *regs; 1871 bool wasup; 1872 uint corerev; 1873 uint32 coreinfo; 1874 uint memsize = 0; 1875 1876 sii = SI_INFO(sih); 1877 1878 /* Block ints and save current core */ 1879 INTR_OFF(sii, intr_val); 1880 origidx = si_coreidx(sih); 1881 1882 /* Switch to SOCRAM core */ 1883 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1884 goto done; 1885 1886 /* Get info for determining size */ 1887 if (!(wasup = si_iscoreup(sih))) 1888 si_core_reset(sih, 0, 0); 1889 corerev = si_corerev(sih); 1890 coreinfo = R_REG(sii->osh, ®s->coreinfo); 1891 1892 /* Calculate size from coreinfo based on rev */ 1893 if (corerev == 0) 1894 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); 1895 else if (corerev < 3) { 1896 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); 1897 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1898 } else if ((corerev <= 7) || (corerev == 12)) { 1899 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1900 uint bsz = (coreinfo & SRCI_SRBSZ_MASK); 1901 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 1902 if (lss != 0) 1903 nb --; 1904 memsize = nb * (1 << (bsz + SR_BSZ_BASE)); 1905 if (lss != 0) 1906 memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 1907 } else { 1908 uint8 i; 1909 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1910 for (i = 0; i < nb; i++) 1911 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); 1912 } 1913 1914 /* Return to previous state and core */ 1915 if (!wasup) 1916 si_core_disable(sih, 0); 1917 si_setcoreidx(sih, origidx); 1918 1919done: 1920 INTR_RESTORE(sii, intr_val); 1921 1922 return memsize; 1923} 1924 1925uint32 1926si_socram_srmem_size(si_t *sih) 1927{ 1928 si_info_t *sii; 1929 uint origidx; 1930 uint intr_val = 0; 1931 1932 sbsocramregs_t *regs; 1933 bool wasup; 1934 uint corerev; 1935 uint32 coreinfo; 1936 uint memsize = 0; 1937 1938 sii = SI_INFO(sih); 1939 1940 /* Block ints and save current core */ 1941 INTR_OFF(sii, intr_val); 1942 origidx = si_coreidx(sih); 1943 1944 /* Switch to SOCRAM core */ 1945 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 1946 goto done; 1947 1948 /* Get info for determining size */ 1949 if (!(wasup = si_iscoreup(sih))) 1950 si_core_reset(sih, 0, 0); 1951 corerev = si_corerev(sih); 1952 coreinfo = R_REG(sii->osh, ®s->coreinfo); 1953 1954 /* Calculate size from coreinfo based on rev */ 1955 if (corerev >= 16) { 1956 uint8 i; 1957 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 1958 for (i = 0; i < nb; i++) { 1959 W_REG(sii->osh, ®s->bankidx, i); 1960 if (R_REG(sii->osh, ®s->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK) 1961 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); 1962 } 1963 } 1964 1965 /* Return to previous state and core */ 1966 if (!wasup) 1967 si_core_disable(sih, 0); 1968 si_setcoreidx(sih, origidx); 1969 1970done: 1971 INTR_RESTORE(sii, intr_val); 1972 1973 return memsize; 1974} 1975 1976 1977void 1978si_btcgpiowar(si_t *sih) 1979{ 1980 si_info_t *sii; 1981 uint origidx; 1982 uint intr_val = 0; 1983 chipcregs_t *cc; 1984 1985 sii = SI_INFO(sih); 1986 1987 /* Make sure that there is ChipCommon core present && 1988 * UART_TX is strapped to 1 1989 */ 1990 if (!(sih->cccaps & CC_CAP_UARTGPIO)) 1991 return; 1992 1993 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ 1994 INTR_OFF(sii, intr_val); 1995 1996 origidx = si_coreidx(sih); 1997 1998 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 1999 ASSERT(cc != NULL); 2000 2001 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); 2002 2003 /* restore the original index */ 2004 si_setcoreidx(sih, origidx); 2005 2006 INTR_RESTORE(sii, intr_val); 2007} 2008 2009void 2010si_chipcontrl_btshd0_4331(si_t *sih, bool on) 2011{ 2012 si_info_t *sii; 2013 chipcregs_t *cc; 2014 uint origidx; 2015 uint32 val; 2016 uint intr_val = 0; 2017 2018 sii = SI_INFO(sih); 2019 2020 INTR_OFF(sii, intr_val); 2021 2022 origidx = si_coreidx(sih); 2023 2024 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2025 2026 val = R_REG(sii->osh, &cc->chipcontrol); 2027 2028 /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */ 2029 if (on) { 2030 /* Enable bt_shd0 on gpio4: */ 2031 val |= (CCTRL4331_BT_SHD0_ON_GPIO4); 2032 W_REG(sii->osh, &cc->chipcontrol, val); 2033 } else { 2034 val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4); 2035 W_REG(sii->osh, &cc->chipcontrol, val); 2036 } 2037 2038 /* restore the original index */ 2039 si_setcoreidx(sih, origidx); 2040 2041 INTR_RESTORE(sii, intr_val); 2042} 2043 2044void 2045si_chipcontrl_restore(si_t *sih, uint32 val) 2046{ 2047 si_info_t *sii; 2048 chipcregs_t *cc; 2049 uint origidx; 2050 2051 sii = SI_INFO(sih); 2052 origidx = si_coreidx(sih); 2053 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2054 W_REG(sii->osh, &cc->chipcontrol, val); 2055 si_setcoreidx(sih, origidx); 2056} 2057 2058uint32 2059si_chipcontrl_read(si_t *sih) 2060{ 2061 si_info_t *sii; 2062 chipcregs_t *cc; 2063 uint origidx; 2064 uint32 val; 2065 2066 sii = SI_INFO(sih); 2067 origidx = si_coreidx(sih); 2068 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2069 val = R_REG(sii->osh, &cc->chipcontrol); 2070 si_setcoreidx(sih, origidx); 2071 return val; 2072} 2073 2074void 2075si_chipcontrl_epa4331(si_t *sih, bool on) 2076{ 2077 si_info_t *sii; 2078 chipcregs_t *cc; 2079 uint origidx; 2080 uint32 val; 2081 2082 sii = SI_INFO(sih); 2083 origidx = si_coreidx(sih); 2084 2085 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2086 2087 val = R_REG(sii->osh, &cc->chipcontrol); 2088 2089 if (on) { 2090 if (sih->chippkg == 9 || sih->chippkg == 0xb) { 2091 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); 2092 /* Ext PA Controls for 4331 12x9 Package */ 2093 W_REG(sii->osh, &cc->chipcontrol, val); 2094 } else { 2095 /* Ext PA Controls for 4331 12x12 Package */ 2096 if (sih->chiprev > 0) { 2097 W_REG(sii->osh, &cc->chipcontrol, val | 2098 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2)); 2099 } else { 2100 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); 2101 } 2102 } 2103 } else { 2104 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5); 2105 W_REG(sii->osh, &cc->chipcontrol, val); 2106 } 2107 2108 si_setcoreidx(sih, origidx); 2109} 2110 2111/* switch muxed pins, on: SROM, off: FEMCTRL */ 2112void 2113si_chipcontrl_srom4360(si_t *sih, bool on) 2114{ 2115 si_info_t *sii; 2116 chipcregs_t *cc; 2117 uint origidx; 2118 uint32 val; 2119 2120 sii = SI_INFO(sih); 2121 origidx = si_coreidx(sih); 2122 2123 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2124 2125 val = R_REG(sii->osh, &cc->chipcontrol); 2126 2127 if (on) { 2128 val &= ~(CCTRL4360_SECI_MODE | 2129 CCTRL4360_BTSWCTRL_MODE | 2130 CCTRL4360_EXTRA_FEMCTRL_MODE | 2131 CCTRL4360_BT_LGCY_MODE | 2132 CCTRL4360_CORE2FEMCTRL4_ON); 2133 2134 W_REG(sii->osh, &cc->chipcontrol, val); 2135 } else { 2136 } 2137 2138 si_setcoreidx(sih, origidx); 2139} 2140 2141void 2142si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) 2143{ 2144 si_info_t *sii; 2145 chipcregs_t *cc; 2146 uint origidx; 2147 uint32 val; 2148 bool sel_chip; 2149 2150 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) || 2151 (CHIPID(sih->chip) == BCM43431_CHIP_ID); 2152 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb)); 2153 2154 if (!sel_chip) 2155 return; 2156 2157 sii = SI_INFO(sih); 2158 origidx = si_coreidx(sih); 2159 2160 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2161 2162 val = R_REG(sii->osh, &cc->chipcontrol); 2163 2164 if (enter_wowl) { 2165 val |= CCTRL4331_EXTPA_EN; 2166 W_REG(sii->osh, &cc->chipcontrol, val); 2167 } else { 2168 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); 2169 W_REG(sii->osh, &cc->chipcontrol, val); 2170 } 2171 si_setcoreidx(sih, origidx); 2172} 2173 2174uint 2175si_pll_reset(si_t *sih) 2176{ 2177 uint err = 0; 2178 2179 return (err); 2180} 2181 2182/* Enable BT-COEX & Ex-PA for 4313 */ 2183void 2184si_epa_4313war(si_t *sih) 2185{ 2186 si_info_t *sii; 2187 chipcregs_t *cc; 2188 uint origidx; 2189 2190 sii = SI_INFO(sih); 2191 origidx = si_coreidx(sih); 2192 2193 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2194 2195 /* EPA Fix */ 2196 W_REG(sii->osh, &cc->gpiocontrol, 2197 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); 2198 2199 si_setcoreidx(sih, origidx); 2200} 2201 2202void 2203si_clk_pmu_htavail_set(si_t *sih, bool set_clear) 2204{ 2205} 2206 2207/* WL/BT control for 4313 btcombo boards >= P250 */ 2208void 2209si_btcombo_p250_4313_war(si_t *sih) 2210{ 2211 si_info_t *sii; 2212 chipcregs_t *cc; 2213 uint origidx; 2214 2215 sii = SI_INFO(sih); 2216 origidx = si_coreidx(sih); 2217 2218 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2219 W_REG(sii->osh, &cc->gpiocontrol, 2220 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK); 2221 2222 W_REG(sii->osh, &cc->gpioouten, 2223 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK); 2224 2225 si_setcoreidx(sih, origidx); 2226} 2227void 2228si_btc_enable_chipcontrol(si_t *sih) 2229{ 2230 si_info_t *sii; 2231 chipcregs_t *cc; 2232 uint origidx; 2233 2234 sii = SI_INFO(sih); 2235 origidx = si_coreidx(sih); 2236 2237 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2238 2239 /* BT fix */ 2240 W_REG(sii->osh, &cc->chipcontrol, 2241 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK); 2242 2243 si_setcoreidx(sih, origidx); 2244} 2245void 2246si_btcombo_43228_war(si_t *sih) 2247{ 2248 si_info_t *sii; 2249 chipcregs_t *cc; 2250 uint origidx; 2251 2252 sii = SI_INFO(sih); 2253 origidx = si_coreidx(sih); 2254 2255 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2256 2257 W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK); 2258 W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK); 2259 2260 si_setcoreidx(sih, origidx); 2261} 2262 2263/* check if the device is removed */ 2264bool 2265si_deviceremoved(si_t *sih) 2266{ 2267 uint32 w; 2268 si_info_t *sii; 2269 2270 sii = SI_INFO(sih); 2271 2272 switch (BUSTYPE(sih->bustype)) { 2273 case PCI_BUS: 2274 ASSERT(sii->osh != NULL); 2275 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); 2276 if ((w & 0xFFFF) != VENDOR_BROADCOM) 2277 return TRUE; 2278 break; 2279 } 2280 return FALSE; 2281} 2282 2283bool 2284si_is_sprom_available(si_t *sih) 2285{ 2286 if (sih->ccrev >= 31) { 2287 si_info_t *sii; 2288 uint origidx; 2289 chipcregs_t *cc; 2290 uint32 sromctrl; 2291 2292 if ((sih->cccaps & CC_CAP_SROM) == 0) 2293 return FALSE; 2294 2295 sii = SI_INFO(sih); 2296 origidx = sii->curidx; 2297 cc = si_setcoreidx(sih, SI_CC_IDX); 2298 sromctrl = R_REG(sii->osh, &cc->sromcontrol); 2299 si_setcoreidx(sih, origidx); 2300 return (sromctrl & SRC_PRESENT); 2301 } 2302 2303 switch (CHIPID(sih->chip)) { 2304 case BCM4312_CHIP_ID: 2305 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); 2306 case BCM4325_CHIP_ID: 2307 return (sih->chipst & CST4325_SPROM_SEL) != 0; 2308 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: 2309 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: 2310 case BCM4342_CHIP_ID: { 2311 uint32 spromotp; 2312 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> 2313 CST4322_SPROM_OTP_SEL_SHIFT; 2314 return (spromotp & CST4322_SPROM_PRESENT) != 0; 2315 } 2316 case BCM4329_CHIP_ID: 2317 return (sih->chipst & CST4329_SPROM_SEL) != 0; 2318 case BCM4315_CHIP_ID: 2319 return (sih->chipst & CST4315_SPROM_SEL) != 0; 2320 case BCM4319_CHIP_ID: 2321 return (sih->chipst & CST4319_SPROM_SEL) != 0; 2322 case BCM4336_CHIP_ID: 2323 case BCM43362_CHIP_ID: 2324 return (sih->chipst & CST4336_SPROM_PRESENT) != 0; 2325 case BCM4330_CHIP_ID: 2326 return (sih->chipst & CST4330_SPROM_PRESENT) != 0; 2327 case BCM4313_CHIP_ID: 2328 return (sih->chipst & CST4313_SPROM_PRESENT) != 0; 2329 case BCM4331_CHIP_ID: 2330 case BCM43431_CHIP_ID: 2331 return (sih->chipst & CST4331_SPROM_PRESENT) != 0; 2332 case BCM43239_CHIP_ID: 2333 return ((sih->chipst & CST43239_SPROM_MASK) && 2334 !(sih->chipst & CST43239_SFLASH_MASK)); 2335 case BCM4324_CHIP_ID: 2336 return ((sih->chipst & CST4324_SPROM_MASK) && 2337 !(sih->chipst & CST4324_SFLASH_MASK)); 2338 case BCM43131_CHIP_ID: 2339 case BCM43217_CHIP_ID: 2340 case BCM43227_CHIP_ID: 2341 case BCM43228_CHIP_ID: 2342 case BCM43428_CHIP_ID: 2343 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; 2344 default: 2345 return TRUE; 2346 } 2347} 2348