1/* 2 * Misc utility routines for accessing chip-specific features 3 * of the SiliconBackplane-based Broadcom chips. 4 * 5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * 19 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $ 20 */ 21 22#include <typedefs.h> 23#include <bcmdefs.h> 24#include <osl.h> 25#include <bcmutils.h> 26#include <siutils.h> 27#include <bcmdevs.h> 28#include <hndsoc.h> 29#include <sbchipc.h> 30#include <pci_core.h> 31#include <pcie_core.h> 32#include <nicpci.h> 33#include <bcmnvram.h> 34#include <bcmsrom.h> 35#include <hndtcam.h> 36#include <pcicfg.h> 37#include <sbpcmcia.h> 38#include <sbsocram.h> 39#include <bcmotp.h> 40#include <hndpmu.h> 41#ifdef BCMSPI 42#include <spid.h> 43#endif /* BCMSPI */ 44 45#include "siutils_priv.h" 46 47/* local prototypes */ 48static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, 49 uint bustype, void *sdh, char **vars, uint *varsz); 50static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); 51static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 52 uint *origidx, void *regs); 53static void si_nvram_process(si_info_t *sii, char *pvars); 54#if !defined(_CFE_) || defined(CFG_WL) 55static void si_sromvars_fixup_4331(si_t *sih, char *pvars); 56#endif /* !_CFE_ || CFG_WL */ 57 58/* dev path concatenation util */ 59static char *si_devpathvar(si_t *sih, char *var, int len, const char *name); 60static bool _si_clkctl_cc(si_info_t *sii, uint mode); 61static bool si_ispcie(si_info_t *sii); 62static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype); 63 64 65/* global variable to indicate reservation/release of gpio's */ 66static uint32 si_gpioreservation = 0; 67 68/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ 69 70/* 71 * Allocate a si handle. 72 * devid - pci device id (used to determine chip#) 73 * osh - opaque OS handle 74 * regs - virtual address of initial core registers 75 * bustype - pci/pcmcia/sb/sdio/etc 76 * vars - pointer to a pointer area for "environment" variables 77 * varsz - pointer to int to return the size of the vars 78 */ 79si_t * 80BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs, 81 uint bustype, void *sdh, char **vars, uint *varsz) 82{ 83 si_info_t *sii; 84 85 /* alloc si_info_t */ 86 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { 87 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); 88 return (NULL); 89 } 90 91 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { 92 MFREE(osh, sii, sizeof(si_info_t)); 93 return (NULL); 94 } 95 sii->vars = vars ? *vars : NULL; 96 sii->varsz = varsz ? *varsz : 0; 97 98 return (si_t *)sii; 99} 100 101/* global kernel resource */ 102static si_info_t ksii; 103 104static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ 105 106/* generic kernel variant of si_attach() */ 107si_t * 108BCMATTACHFN(si_kattach)(osl_t *osh) 109{ 110 static bool ksii_attached = FALSE; 111 112 if (!ksii_attached) { 113 void *regs; 114#ifndef SI_ENUM_BASE_VARIABLE 115 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 116#endif 117 118 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, 119 SI_BUS, NULL, 120 osh != SI_OSH ? &ksii.vars : NULL, 121 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { 122 SI_ERROR(("si_kattach: si_doattach failed\n")); 123 REG_UNMAP(regs); 124 return NULL; 125 } 126 REG_UNMAP(regs); 127 128 /* save ticks normalized to ms for si_watchdog_ms() */ 129 if (PMUCTL_ENAB(&ksii.pub)) { 130 if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) { 131 /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ 132 wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000; 133 } 134 else 135 /* based on 32KHz ILP clock */ 136 wd_msticks = 32; 137 } else { 138 if (ksii.pub.ccrev < 18) 139 wd_msticks = si_clock(&ksii.pub) / 1000; 140 else 141 wd_msticks = si_alp_clock(&ksii.pub) / 1000; 142 } 143 144 ksii_attached = TRUE; 145 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", 146 ksii.pub.ccrev, wd_msticks)); 147 } 148 149 return &ksii.pub; 150} 151 152bool 153si_ldo_war(si_t *sih, uint devid) 154{ 155 si_info_t *sii = SI_INFO(sih); 156 uint32 w; 157 chipcregs_t *cc; 158 void *regs = sii->curmap; 159 uint32 rev_id, ccst; 160 161 rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32)); 162 rev_id &= 0xff; 163 if (!(((CHIPID(devid) == BCM4322_CHIP_ID) || 164 (CHIPID(devid) == BCM4342_CHIP_ID) || 165 (CHIPID(devid) == BCM4322_D11N_ID) || 166 (CHIPID(devid) == BCM4322_D11N2G_ID) || 167 (CHIPID(devid) == BCM4322_D11N5G_ID)) && 168 (rev_id == 0))) 169 return TRUE; 170 171 SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id)); 172 173 /* switch to chipcommon */ 174 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 175 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE); 176 cc = (chipcregs_t *)regs; 177 178 /* clear bit 7 to fix LDO 179 * write to register *blindly* WITHOUT read since read may timeout 180 * because the default clock is 32k ILP 181 */ 182 W_REG(sii->osh, &cc->regcontrol_addr, 0); 183 /* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */ 184 W_REG(sii->osh, &cc->regcontrol_data, 0x3001); 185 186 OSL_DELAY(5000); 187 188 /* request ALP_AVAIL through PMU to move sb out of ILP */ 189 W_REG(sii->osh, &cc->min_res_mask, 0x0d); 190 191 SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL) 192 == 0, PMU_MAX_TRANSITION_DLY); 193 194 if ((ccst & CCS_ALPAVAIL) == 0) { 195 SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst)); 196 return FALSE; 197 } 198 SI_MSG(("si_ldo_war: 4322a0 HACK done\n")); 199 200 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w); 201 202 return TRUE; 203} 204 205static bool 206BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh) 207{ 208 /* need to set memseg flag for CF card first before any sb registers access */ 209 if (BUSTYPE(bustype) == PCMCIA_BUS) 210 sii->memseg = TRUE; 211 212 if (BUSTYPE(bustype) == PCI_BUS) { 213 if (!si_ldo_war((si_t *)sii, devid)) 214 return FALSE; 215 } 216 217 /* kludge to enable the clock on the 4306 which lacks a slowclock */ 218 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii)) 219 si_clkctl_xtal(&sii->pub, XTAL|PLL, ON); 220 221 222 return TRUE; 223} 224 225static bool 226BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, 227 uint *origidx, void *regs) 228{ 229 bool pci, pcie; 230 uint i; 231 uint pciidx, pcieidx, pcirev, pcierev; 232 233 cc = si_setcoreidx(&sii->pub, SI_CC_IDX); 234 ASSERT((uintptr)cc); 235 236 /* get chipcommon rev */ 237 sii->pub.ccrev = (int)si_corerev(&sii->pub); 238 239 /* get chipcommon chipstatus */ 240 if (sii->pub.ccrev >= 11) 241 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); 242 243 /* get chipcommon capabilites */ 244 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); 245 /* get chipcommon extended capabilities */ 246 247 if (sii->pub.ccrev >= 35) 248 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); 249 250 /* get pmu rev and caps */ 251 if (sii->pub.cccaps & CC_CAP_PMU) { 252 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); 253 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; 254 } 255 256 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", 257 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, 258 sii->pub.pmucaps)); 259 260 /* figure out bus/orignal core idx */ 261 sii->pub.buscoretype = NODEV_CORE_ID; 262 sii->pub.buscorerev = NOREV; 263 sii->pub.buscoreidx = BADIDX; 264 265 pci = pcie = FALSE; 266 pcirev = pcierev = NOREV; 267 pciidx = pcieidx = BADIDX; 268 269 for (i = 0; i < sii->numcores; i++) { 270 uint cid, crev; 271 272 si_setcoreidx(&sii->pub, i); 273 cid = si_coreid(&sii->pub); 274 crev = si_corerev(&sii->pub); 275 276 /* Display cores found */ 277 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", 278 i, cid, crev, sii->coresba[i], sii->regs[i])); 279 280 if (BUSTYPE(bustype) == PCI_BUS) { 281 if (cid == PCI_CORE_ID) { 282 pciidx = i; 283 pcirev = crev; 284 pci = TRUE; 285 } else if (cid == PCIE_CORE_ID) { 286 pcieidx = i; 287 pcierev = crev; 288 pcie = TRUE; 289 } 290 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && 291 (cid == PCMCIA_CORE_ID)) { 292 sii->pub.buscorerev = crev; 293 sii->pub.buscoretype = cid; 294 sii->pub.buscoreidx = i; 295 } 296 297 /* find the core idx before entering this func. */ 298 if ((savewin && (savewin == sii->coresba[i])) || 299 (regs == sii->regs[i])) 300 *origidx = i; 301 } 302 303 if (pci && pcie) { 304 if (si_ispcie(sii)) 305 pci = FALSE; 306 else 307 pcie = FALSE; 308 } 309 if (pci) { 310 sii->pub.buscoretype = PCI_CORE_ID; 311 sii->pub.buscorerev = pcirev; 312 sii->pub.buscoreidx = pciidx; 313 } else if (pcie) { 314 sii->pub.buscoretype = PCIE_CORE_ID; 315 sii->pub.buscorerev = pcierev; 316 sii->pub.buscoreidx = pcieidx; 317 } 318 319 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, 320 sii->pub.buscorerev)); 321 322 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && 323 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3)) 324 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); 325 326 /* fixup necessary chip/core configurations */ 327 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { 328 if (SI_FAST(sii)) { 329 if (!sii->pch && 330 ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh, 331 (void *)PCIEREGS(sii))) == NULL)) 332 return FALSE; 333 } 334 if (si_pci_fixcfg(&sii->pub)) { 335 SI_ERROR(("si_doattach: si_pci_fixcfg failed\n")); 336 return FALSE; 337 } 338 } 339 340 341 /* return to the original core */ 342 si_setcoreidx(&sii->pub, *origidx); 343 344 return TRUE; 345} 346 347static void 348BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars) 349{ 350 uint w = 0; 351 if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) { 352 w = getintvar(pvars, "regwindowsz"); 353 sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE; 354 } 355 356 /* get boardtype and boardrev */ 357 switch (BUSTYPE(sii->pub.bustype)) { 358 case PCI_BUS: 359#if defined(BCMHOSTVARS) 360 sii->pub.boardvendor = VENDOR_BROADCOM; 361 sii->pub.boardtype = getintvar(pvars, "boardtype"); 362#else /* !BCMHOSTVARS */ 363 /* do a pci config read to get subsystem id and subvendor id */ 364 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32)); 365 /* Let nvram variables override subsystem Vend/ID */ 366 if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor")) 367 == 0) 368 sii->pub.boardvendor = w & 0xffff; 369 else 370 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", 371 sii->pub.boardvendor, w & 0xffff)); 372 if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype")) 373 == 0) 374 sii->pub.boardtype = (w >> 16) & 0xffff; 375 else 376 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", 377 sii->pub.boardtype, (w >> 16) & 0xffff)); 378#endif /* BCMHOSTVARS */ 379 break; 380 381 case PCMCIA_BUS: 382 sii->pub.boardvendor = getintvar(pvars, "manfid"); 383 sii->pub.boardtype = getintvar(pvars, "prodid"); 384 break; 385 386 387 case SI_BUS: 388 case JTAG_BUS: 389 sii->pub.boardvendor = VENDOR_BROADCOM; 390 if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0)) 391 if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0) 392 sii->pub.boardtype = 0xffff; 393 394 if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { 395 /* do a pci config read to get subsystem id and subvendor id */ 396 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32)); 397 sii->pub.boardvendor = w & 0xffff; 398 sii->pub.boardtype = (w >> 16) & 0xffff; 399 } 400 break; 401 } 402 403 if (sii->pub.boardtype == 0) { 404 SI_ERROR(("si_doattach: unknown board type\n")); 405 ASSERT(sii->pub.boardtype); 406 } 407 408 sii->pub.boardrev = getintvar(pvars, "boardrev"); 409 sii->pub.boardflags = getintvar(pvars, "boardflags"); 410} 411 412#if !defined(_CFE_) || defined(CFG_WL) 413static void 414BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars) 415{ 416 417 const char *sromvars[] = 418 {"extpagain2g", "extpagain5g"}; 419 int sromvars_size = sizeof(sromvars)/sizeof(char *); 420 int ii; 421 uint boardtype = sih->boardtype; 422 uint boardrev = sih->boardrev; 423 bool update = ((boardtype == BCM94331BU_SSID) || 424 (boardtype == BCM94331S9BU_SSID) || 425 (boardtype == BCM94331MCI_SSID) || 426 (boardtype == BCM94331MC_SSID) || 427 (boardtype == BCM94331PCIEBT4_SSID) || 428 (boardtype == BCM94331X19 && boardrev == 0x1100) || 429 (boardtype == BCM94331HM_SSID && boardrev < 0x1152)); 430 431 if (pvars == NULL || !update) { 432 return; 433 } 434 435 for (ii = 0; ii < sromvars_size; ii++) { 436 char* val = getvar(pvars, sromvars[ii]); 437 438 while (val && *val) { 439 *val = '0'; 440 val++; 441 } 442 } 443} 444#endif /* !_CFE_ || CFG_WL */ 445 446#ifdef CONFIG_XIP 447extern uint8 patch_pair; 448#endif /* CONFIG_XIP */ 449 450static si_info_t * 451BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, 452 uint bustype, void *sdh, char **vars, uint *varsz) 453{ 454 struct si_pub *sih = &sii->pub; 455 uint32 w, savewin; 456 chipcregs_t *cc; 457 char *pvars = NULL; 458 uint origidx; 459 460 ASSERT(GOODREGS(regs)); 461 462 bzero((uchar*)sii, sizeof(si_info_t)); 463 464 savewin = 0; 465 466 sih->buscoreidx = BADIDX; 467 468 sii->curmap = regs; 469 sii->sdh = sdh; 470 sii->osh = osh; 471 472#ifdef SI_ENUM_BASE_VARIABLE 473 si_enum_base_init(sih, bustype); 474#endif /* SI_ENUM_BASE_VARIABLE */ 475 476 /* check to see if we are a si core mimic'ing a pci core */ 477 if ((bustype == PCI_BUS) && 478 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) { 479 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " 480 "devid:0x%x\n", __FUNCTION__, devid)); 481 bustype = SI_BUS; 482 } 483 484 /* find Chipcommon address */ 485 if (bustype == PCI_BUS) { 486 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); 487 if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) 488 savewin = SI_ENUM_BASE; 489 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); 490 cc = (chipcregs_t *)regs; 491 } else { 492 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); 493 } 494 495 sih->bustype = bustype; 496 if (bustype != BUSTYPE(bustype)) { 497 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", 498 bustype, BUSTYPE(bustype))); 499 return NULL; 500 } 501 502 /* bus/core/clk setup for register access */ 503 if (!si_buscore_prep(sii, bustype, devid, sdh)) { 504 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); 505 return NULL; 506 } 507 508 /* ChipID recognition. 509 * We assume we can read chipid at offset 0 from the regs arg. 510 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), 511 * some way of recognizing them needs to be added here. 512 */ 513 w = R_REG(osh, &cc->chipid); 514 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; 515 /* Might as wll fill in chip id rev & pkg */ 516 sih->chip = w & CID_ID_MASK; 517 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; 518 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; 519 520 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && 521 (sih->chippkg != BCM4329_289PIN_PKG_ID)) { 522 sih->chippkg = BCM4329_182PIN_PKG_ID; 523 } 524 sih->issim = IS_SIM(sih->chippkg); 525 526 /* scan for cores */ 527 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { 528 SI_MSG(("Found chip type SB (0x%08x)\n", w)); 529 sb_scan(&sii->pub, regs, devid); 530 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { 531 SI_MSG(("Found chip type AI (0x%08x)\n", w)); 532 /* pass chipc address instead of original core base */ 533 ai_scan(&sii->pub, (void *)(uintptr)cc, devid); 534 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { 535 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); 536 /* pass chipc address instead of original core base */ 537 ub_scan(&sii->pub, (void *)(uintptr)cc, devid); 538 } else { 539 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); 540 return NULL; 541 } 542 /* no cores found, bail out */ 543 if (sii->numcores == 0) { 544 SI_ERROR(("si_doattach: could not find any cores\n")); 545 return NULL; 546 } 547 /* bus/core/clk setup */ 548 origidx = SI_CC_IDX; 549 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { 550 SI_ERROR(("si_doattach: si_buscore_setup failed\n")); 551 goto exit; 552 } 553 554#if !defined(_CFE_) || defined(CFG_WL) 555 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) 556 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | 557 CST4322_SPROM_PRESENT))) { 558 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__)); 559 return NULL; 560 } 561 562 /* assume current core is CC */ 563 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || 564 CHIPID(sih->chip) == BCM43235_CHIP_ID || 565 CHIPID(sih->chip) == BCM43234_CHIP_ID || 566 CHIPID(sih->chip) == BCM43238_CHIP_ID) && 567 (CHIPREV(sii->pub.chiprev) <= 2))) { 568 569 if ((cc->chipstatus & CST43236_BP_CLK) != 0) { 570 uint clkdiv; 571 clkdiv = R_REG(osh, &cc->clkdiv); 572 /* otp_clk_div is even number, 120/14 < 9mhz */ 573 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT); 574 W_REG(osh, &cc->clkdiv, clkdiv); 575 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); 576 } 577 OSL_DELAY(10); 578 } 579 580 if (bustype == PCI_BUS) { 581 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || 582 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { 583 /* set default mux pin to SROM */ 584 si_chipcontrl_epa4331(sih, FALSE); 585 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100); 586 OSL_DELAY(20000); /* Srom read takes ~12mS */ 587 } 588 } 589#endif /* !_CFE_ || CFG_WL */ 590#ifdef SI_SPROM_PROBE 591 si_sprom_init(sih); 592#endif /* SI_SPROM_PROBE */ 593 594#if !defined(BCMHIGHSDIO) 595 /* Init nvram from flash if it exists */ 596 nvram_init((void *)&(sii->pub)); 597 598 /* Init nvram from sprom/otp if they exist */ 599 if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) { 600 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n")); 601 goto exit; 602 } 603 pvars = vars ? *vars : NULL; 604 si_nvram_process(sii, pvars); 605 606#if !defined(_CFE_) || defined(CFG_WL) 607 if (bustype == PCI_BUS) { 608 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || 609 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { 610 si_sromvars_fixup_4331(sih, pvars); 611 } 612 } 613#endif /* _!CFE_ || CFG_WL */ 614 615 /* === NVRAM, clock is ready === */ 616#else 617 pvars = NULL; 618#endif 619 620 621#ifdef CONFIG_XIP 622 /* patch the ROM if there are any patch pairs from OTP/SPROM */ 623 if (patch_pair) { 624 625 hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars); 626 627 si_setcoreidx(sih, origidx); 628 } 629#endif /* CONFIG_XIP */ 630 631 if (sii->pub.ccrev >= 20) { 632 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 633 W_REG(osh, &cc->gpiopullup, 0); 634 W_REG(osh, &cc->gpiopulldown, 0); 635 si_setcoreidx(sih, origidx); 636 } 637 638 /* PMU specific initializations */ 639 if (PMUCTL_ENAB(sih)) { 640 uint32 xtalfreq; 641 si_pmu_init(sih, sii->osh); 642 si_pmu_chip_init(sih, sii->osh); 643 xtalfreq = getintvar(pvars, "xtalfreq"); 644 /* If xtalfreq var not available, try to measure it */ 645 if (xtalfreq == 0) 646 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh); 647 si_pmu_pll_init(sih, sii->osh, xtalfreq); 648 si_pmu_res_init(sih, sii->osh); 649 si_pmu_swreg_init(sih, sii->osh); 650 } 651 652 /* setup the GPIO based LED powersave register */ 653 if (sii->pub.ccrev >= 16) { 654 if ((w = getintvar(pvars, "leddc")) == 0) 655 w = DEFAULT_GPIOTIMERVAL; 656 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); 657 } 658 659 if (PCI_FORCEHT(sii)) { 660 SI_MSG(("si_doattach: force HT\n")); 661 sih->pci_pr32414 = TRUE; 662 si_clkctl_init(sih); 663 _si_clkctl_cc(sii, CLK_FAST); 664 } 665 666#if !defined(_CFE_) || defined(CFG_WL) 667 if (PCIE(sii)) { 668 ASSERT(sii->pch != NULL); 669 670 pcicore_attach(sii->pch, pvars, SI_DOATTACH); 671 672 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) || 673 (CHIPID(sih->chip) == BCM4312_CHIP_ID)) { 674 SI_MSG(("si_doattach: clear initiator timeout\n")); 675 sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0)); 676 } 677 } 678 679 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) || 680 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) { 681 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */ 682 if (CHIPREV(sih->chiprev) == 0) { 683 SI_MSG(("Applying 43224A0 WARs\n")); 684 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), 685 CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE); 686 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, 687 CCTRL_43224A0_12MA_LED_DRIVE); 688 } 689 if (CHIPREV(sih->chiprev) >= 1) { 690 SI_MSG(("Applying 43224B0+ WARs\n")); 691 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, 692 CCTRL_43224B0_12MA_LED_DRIVE); 693 } 694 } 695 696 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) { 697 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */ 698 SI_MSG(("Applying 4313 WARs\n")); 699 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, CCTRL_4313_12MA_LED_DRIVE); 700 } 701#endif /* !_CFE_ || CFG_WL */ 702 703 704 return (sii); 705 706exit: 707 if (BUSTYPE(sih->bustype) == PCI_BUS) { 708 if (sii->pch) 709 pcicore_deinit(sii->pch); 710 sii->pch = NULL; 711 } 712 713 return NULL; 714} 715 716/* may be called with core in reset */ 717void 718BCMATTACHFN(si_detach)(si_t *sih) 719{ 720 si_info_t *sii; 721 uint idx; 722 723#if defined(STA) 724 struct si_pub *si_local = NULL; 725 bcopy(&sih, &si_local, sizeof(si_t**)); 726#endif 727 728 sii = SI_INFO(sih); 729 730 if (sii == NULL) 731 return; 732 733 if (BUSTYPE(sih->bustype) == SI_BUS) 734 for (idx = 0; idx < SI_MAXCORES; idx++) 735 if (sii->regs[idx]) { 736 REG_UNMAP(sii->regs[idx]); 737 sii->regs[idx] = NULL; 738 } 739 740#if defined(STA) 741 nvram_exit((void *)si_local); /* free up nvram buffers */ 742#endif 743 744 if (BUSTYPE(sih->bustype) == PCI_BUS) { 745 if (sii->pch) 746 pcicore_deinit(sii->pch); 747 sii->pch = NULL; 748 } 749 750#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) 751 if (sii != &ksii) 752#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ 753 MFREE(sii->osh, sii, sizeof(si_info_t)); 754} 755 756void * 757si_osh(si_t *sih) 758{ 759 si_info_t *sii; 760 761 sii = SI_INFO(sih); 762 return sii->osh; 763} 764 765void 766si_setosh(si_t *sih, osl_t *osh) 767{ 768 si_info_t *sii; 769 770 sii = SI_INFO(sih); 771 if (sii->osh != NULL) { 772 SI_ERROR(("osh is already set....\n")); 773 ASSERT(!sii->osh); 774 } 775 sii->osh = osh; 776} 777 778/* register driver interrupt disabling and restoring callback functions */ 779void 780si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, 781 void *intrsenabled_fn, void *intr_arg) 782{ 783 si_info_t *sii; 784 785 sii = SI_INFO(sih); 786 sii->intr_arg = intr_arg; 787 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; 788 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; 789 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; 790 /* save current core id. when this function called, the current core 791 * must be the core which provides driver functions(il, et, wl, etc.) 792 */ 793 sii->dev_coreid = sii->coreid[sii->curidx]; 794} 795 796void 797si_deregister_intr_callback(si_t *sih) 798{ 799 si_info_t *sii; 800 801 sii = SI_INFO(sih); 802 sii->intrsoff_fn = NULL; 803} 804 805uint 806si_intflag(si_t *sih) 807{ 808 si_info_t *sii = SI_INFO(sih); 809 810 if (CHIPTYPE(sih->socitype) == SOCI_SB) 811 return sb_intflag(sih); 812 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 813 return R_REG(sii->osh, ((uint32 *)(uintptr) 814 (sii->oob_router + OOB_STATUSA))); 815 else { 816 ASSERT(0); 817 return 0; 818 } 819} 820 821uint 822si_flag(si_t *sih) 823{ 824 if (CHIPTYPE(sih->socitype) == SOCI_SB) 825 return sb_flag(sih); 826 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 827 return ai_flag(sih); 828 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 829 return ub_flag(sih); 830 else { 831 ASSERT(0); 832 return 0; 833 } 834} 835 836void 837si_setint(si_t *sih, int siflag) 838{ 839 if (CHIPTYPE(sih->socitype) == SOCI_SB) 840 sb_setint(sih, siflag); 841 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 842 ai_setint(sih, siflag); 843 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 844 ub_setint(sih, siflag); 845 else 846 ASSERT(0); 847} 848 849uint 850si_coreid(si_t *sih) 851{ 852 si_info_t *sii; 853 854 sii = SI_INFO(sih); 855 return sii->coreid[sii->curidx]; 856} 857 858uint 859si_coreidx(si_t *sih) 860{ 861 si_info_t *sii; 862 863 sii = SI_INFO(sih); 864 return sii->curidx; 865} 866 867/* return the core-type instantiation # of the current core */ 868uint 869si_coreunit(si_t *sih) 870{ 871 si_info_t *sii; 872 uint idx; 873 uint coreid; 874 uint coreunit; 875 uint i; 876 877 sii = SI_INFO(sih); 878 coreunit = 0; 879 880 idx = sii->curidx; 881 882 ASSERT(GOODREGS(sii->curmap)); 883 coreid = si_coreid(sih); 884 885 /* count the cores of our type */ 886 for (i = 0; i < idx; i++) 887 if (sii->coreid[i] == coreid) 888 coreunit++; 889 890 return (coreunit); 891} 892 893uint 894si_corevendor(si_t *sih) 895{ 896 if (CHIPTYPE(sih->socitype) == SOCI_SB) 897 return sb_corevendor(sih); 898 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 899 return ai_corevendor(sih); 900 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 901 return ub_corevendor(sih); 902 else { 903 ASSERT(0); 904 return 0; 905 } 906} 907 908bool 909si_backplane64(si_t *sih) 910{ 911 return ((sih->cccaps & CC_CAP_BKPLN64) != 0); 912} 913 914uint 915si_corerev(si_t *sih) 916{ 917 if (CHIPTYPE(sih->socitype) == SOCI_SB) 918 return sb_corerev(sih); 919 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 920 return ai_corerev(sih); 921 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 922 return ub_corerev(sih); 923 else { 924 ASSERT(0); 925 return 0; 926 } 927} 928 929/* return index of coreid or BADIDX if not found */ 930uint 931si_findcoreidx(si_t *sih, uint coreid, uint coreunit) 932{ 933 si_info_t *sii; 934 uint found; 935 uint i; 936 937 sii = SI_INFO(sih); 938 939 found = 0; 940 941 for (i = 0; i < sii->numcores; i++) 942 if (sii->coreid[i] == coreid) { 943 if (found == coreunit) 944 return (i); 945 found++; 946 } 947 948 return (BADIDX); 949} 950 951/* return list of found cores */ 952uint 953si_corelist(si_t *sih, uint coreid[]) 954{ 955 si_info_t *sii; 956 957 sii = SI_INFO(sih); 958 959 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); 960 return (sii->numcores); 961} 962 963/* return current register mapping */ 964void * 965si_coreregs(si_t *sih) 966{ 967 si_info_t *sii; 968 969 sii = SI_INFO(sih); 970 ASSERT(GOODREGS(sii->curmap)); 971 972 return (sii->curmap); 973} 974 975/* 976 * This function changes logical "focus" to the indicated core; 977 * must be called with interrupts off. 978 * Moreover, callers should keep interrupts off during switching out of and back to d11 core 979 */ 980void * 981si_setcore(si_t *sih, uint coreid, uint coreunit) 982{ 983 uint idx; 984 985 idx = si_findcoreidx(sih, coreid, coreunit); 986 if (!GOODIDX(idx)) 987 return (NULL); 988 989 if (CHIPTYPE(sih->socitype) == SOCI_SB) 990 return sb_setcoreidx(sih, idx); 991 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 992 return ai_setcoreidx(sih, idx); 993 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 994 return ub_setcoreidx(sih, idx); 995 else { 996 ASSERT(0); 997 return NULL; 998 } 999} 1000 1001void * 1002si_setcoreidx(si_t *sih, uint coreidx) 1003{ 1004 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1005 return sb_setcoreidx(sih, coreidx); 1006 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1007 return ai_setcoreidx(sih, coreidx); 1008 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1009 return ub_setcoreidx(sih, coreidx); 1010 else { 1011 ASSERT(0); 1012 return NULL; 1013 } 1014} 1015 1016/* Turn off interrupt as required by sb_setcore, before switch core */ 1017void * 1018si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) 1019{ 1020 void *cc; 1021 si_info_t *sii; 1022 1023 sii = SI_INFO(sih); 1024 1025 if (SI_FAST(sii)) { 1026 /* Overloading the origidx variable to remember the coreid, 1027 * this works because the core ids cannot be confused with 1028 * core indices. 1029 */ 1030 *origidx = coreid; 1031 if (coreid == CC_CORE_ID) 1032 return (void *)CCREGS_FAST(sii); 1033 else if (coreid == sih->buscoretype) 1034 return (void *)PCIEREGS(sii); 1035 } 1036 INTR_OFF(sii, *intr_val); 1037 *origidx = sii->curidx; 1038 cc = si_setcore(sih, coreid, 0); 1039 ASSERT(cc != NULL); 1040 1041 return cc; 1042} 1043 1044/* restore coreidx and restore interrupt */ 1045void 1046si_restore_core(si_t *sih, uint coreid, uint intr_val) 1047{ 1048 si_info_t *sii; 1049 1050 sii = SI_INFO(sih); 1051 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) 1052 return; 1053 1054 si_setcoreidx(sih, coreid); 1055 INTR_RESTORE(sii, intr_val); 1056} 1057 1058int 1059si_numaddrspaces(si_t *sih) 1060{ 1061 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1062 return sb_numaddrspaces(sih); 1063 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1064 return ai_numaddrspaces(sih); 1065 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1066 return ub_numaddrspaces(sih); 1067 else { 1068 ASSERT(0); 1069 return 0; 1070 } 1071} 1072 1073uint32 1074si_addrspace(si_t *sih, uint asidx) 1075{ 1076 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1077 return sb_addrspace(sih, asidx); 1078 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1079 return ai_addrspace(sih, asidx); 1080 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1081 return ub_addrspace(sih, asidx); 1082 else { 1083 ASSERT(0); 1084 return 0; 1085 } 1086} 1087 1088uint32 1089si_addrspacesize(si_t *sih, uint asidx) 1090{ 1091 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1092 return sb_addrspacesize(sih, asidx); 1093 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1094 return ai_addrspacesize(sih, asidx); 1095 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1096 return ub_addrspacesize(sih, asidx); 1097 else { 1098 ASSERT(0); 1099 return 0; 1100 } 1101} 1102 1103uint32 1104si_core_cflags(si_t *sih, uint32 mask, uint32 val) 1105{ 1106 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1107 return sb_core_cflags(sih, mask, val); 1108 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1109 return ai_core_cflags(sih, mask, val); 1110 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1111 return ub_core_cflags(sih, mask, val); 1112 else { 1113 ASSERT(0); 1114 return 0; 1115 } 1116} 1117 1118void 1119si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) 1120{ 1121 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1122 sb_core_cflags_wo(sih, mask, val); 1123 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1124 ai_core_cflags_wo(sih, mask, val); 1125 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1126 ub_core_cflags_wo(sih, mask, val); 1127 else 1128 ASSERT(0); 1129} 1130 1131uint32 1132si_core_sflags(si_t *sih, uint32 mask, uint32 val) 1133{ 1134 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1135 return sb_core_sflags(sih, mask, val); 1136 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1137 return ai_core_sflags(sih, mask, val); 1138 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1139 return ub_core_sflags(sih, mask, val); 1140 else { 1141 ASSERT(0); 1142 return 0; 1143 } 1144} 1145 1146bool 1147si_iscoreup(si_t *sih) 1148{ 1149 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1150 return sb_iscoreup(sih); 1151 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1152 return ai_iscoreup(sih); 1153 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1154 return ub_iscoreup(sih); 1155 else { 1156 ASSERT(0); 1157 return FALSE; 1158 } 1159} 1160 1161void 1162si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val) 1163{ 1164 /* only for 4319, no requirement for SOCI_SB */ 1165 if (CHIPTYPE(sih->socitype) == SOCI_AI) { 1166 ai_write_wrap_reg(sih, offset, val); 1167 } 1168 else 1169 return; 1170 1171 return; 1172} 1173 1174uint 1175si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 1176{ 1177 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1178 return sb_corereg(sih, coreidx, regoff, mask, val); 1179 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1180 return ai_corereg(sih, coreidx, regoff, mask, val); 1181 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1182 return ub_corereg(sih, coreidx, regoff, mask, val); 1183 else { 1184 ASSERT(0); 1185 return 0; 1186 } 1187} 1188 1189void 1190si_core_disable(si_t *sih, uint32 bits) 1191{ 1192 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1193 sb_core_disable(sih, bits); 1194 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1195 ai_core_disable(sih, bits); 1196 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1197 ub_core_disable(sih, bits); 1198} 1199 1200void 1201si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) 1202{ 1203 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1204 sb_core_reset(sih, bits, resetbits); 1205 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1206 ai_core_reset(sih, bits, resetbits); 1207 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1208 ub_core_reset(sih, bits, resetbits); 1209} 1210 1211/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ 1212int 1213si_corebist(si_t *sih) 1214{ 1215 uint32 cflags; 1216 int result = 0; 1217 1218 /* Read core control flags */ 1219 cflags = si_core_cflags(sih, 0, 0); 1220 1221 /* Set bist & fgc */ 1222 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); 1223 1224 /* Wait for bist done */ 1225 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); 1226 1227 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) 1228 result = BCME_ERROR; 1229 1230 /* Reset core control flags */ 1231 si_core_cflags(sih, 0xffff, cflags); 1232 1233 return result; 1234} 1235 1236static uint32 1237BCMINITFN(factor6)(uint32 x) 1238{ 1239 switch (x) { 1240 case CC_F6_2: return 2; 1241 case CC_F6_3: return 3; 1242 case CC_F6_4: return 4; 1243 case CC_F6_5: return 5; 1244 case CC_F6_6: return 6; 1245 case CC_F6_7: return 7; 1246 default: return 0; 1247 } 1248} 1249 1250/* calculate the speed the SI would run at given a set of clockcontrol values */ 1251uint32 1252BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m) 1253{ 1254 uint32 n1, n2, clock, m1, m2, m3, mc; 1255 1256 n1 = n & CN_N1_MASK; 1257 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; 1258 1259 if (pll_type == PLL_TYPE6) { 1260 if (m & CC_T6_MMASK) 1261 return CC_T6_M1; 1262 else 1263 return CC_T6_M0; 1264 } else if ((pll_type == PLL_TYPE1) || 1265 (pll_type == PLL_TYPE3) || 1266 (pll_type == PLL_TYPE4) || 1267 (pll_type == PLL_TYPE7)) { 1268 n1 = factor6(n1); 1269 n2 += CC_F5_BIAS; 1270 } else if (pll_type == PLL_TYPE2) { 1271 n1 += CC_T2_BIAS; 1272 n2 += CC_T2_BIAS; 1273 ASSERT((n1 >= 2) && (n1 <= 7)); 1274 ASSERT((n2 >= 5) && (n2 <= 23)); 1275 } else if (pll_type == PLL_TYPE5) { 1276 return (100000000); 1277 } else 1278 ASSERT(0); 1279 /* PLL types 3 and 7 use BASE2 (25Mhz) */ 1280 if ((pll_type == PLL_TYPE3) || 1281 (pll_type == PLL_TYPE7)) { 1282 clock = CC_CLOCK_BASE2 * n1 * n2; 1283 } else 1284 clock = CC_CLOCK_BASE1 * n1 * n2; 1285 1286 if (clock == 0) 1287 return 0; 1288 1289 m1 = m & CC_M1_MASK; 1290 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; 1291 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; 1292 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; 1293 1294 if ((pll_type == PLL_TYPE1) || 1295 (pll_type == PLL_TYPE3) || 1296 (pll_type == PLL_TYPE4) || 1297 (pll_type == PLL_TYPE7)) { 1298 m1 = factor6(m1); 1299 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) 1300 m2 += CC_F5_BIAS; 1301 else 1302 m2 = factor6(m2); 1303 m3 = factor6(m3); 1304 1305 switch (mc) { 1306 case CC_MC_BYPASS: return (clock); 1307 case CC_MC_M1: return (clock / m1); 1308 case CC_MC_M1M2: return (clock / (m1 * m2)); 1309 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); 1310 case CC_MC_M1M3: return (clock / (m1 * m3)); 1311 default: return (0); 1312 } 1313 } else { 1314 ASSERT(pll_type == PLL_TYPE2); 1315 1316 m1 += CC_T2_BIAS; 1317 m2 += CC_T2M2_BIAS; 1318 m3 += CC_T2_BIAS; 1319 ASSERT((m1 >= 2) && (m1 <= 7)); 1320 ASSERT((m2 >= 3) && (m2 <= 10)); 1321 ASSERT((m3 >= 2) && (m3 <= 7)); 1322 1323 if ((mc & CC_T2MC_M1BYP) == 0) 1324 clock /= m1; 1325 if ((mc & CC_T2MC_M2BYP) == 0) 1326 clock /= m2; 1327 if ((mc & CC_T2MC_M3BYP) == 0) 1328 clock /= m3; 1329 1330 return (clock); 1331 } 1332} 1333 1334uint32 1335BCMINITFN(si_clock)(si_t *sih) 1336{ 1337 si_info_t *sii; 1338 chipcregs_t *cc; 1339 uint32 n, m; 1340 uint idx; 1341 uint32 pll_type, rate; 1342 uint intr_val = 0; 1343 1344 sii = SI_INFO(sih); 1345 INTR_OFF(sii, intr_val); 1346 if (PMUCTL_ENAB(sih)) { 1347 rate = si_pmu_si_clock(sih, sii->osh); 1348 goto exit; 1349 } 1350 1351 idx = sii->curidx; 1352 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 1353 ASSERT(cc != NULL); 1354 1355 n = R_REG(sii->osh, &cc->clockcontrol_n); 1356 pll_type = sih->cccaps & CC_CAP_PLL_MASK; 1357 if (pll_type == PLL_TYPE6) 1358 m = R_REG(sii->osh, &cc->clockcontrol_m3); 1359 else if (pll_type == PLL_TYPE3) 1360 m = R_REG(sii->osh, &cc->clockcontrol_m2); 1361 else 1362 m = R_REG(sii->osh, &cc->clockcontrol_sb); 1363 1364 /* calculate rate */ 1365 rate = si_clock_rate(pll_type, n, m); 1366 1367 if (pll_type == PLL_TYPE3) 1368 rate = rate / 2; 1369 1370 /* switch back to previous core */ 1371 si_setcoreidx(sih, idx); 1372exit: 1373 INTR_RESTORE(sii, intr_val); 1374 1375 return rate; 1376} 1377 1378uint32 1379BCMINITFN(si_alp_clock)(si_t *sih) 1380{ 1381 if (PMUCTL_ENAB(sih)) 1382 return si_pmu_alp_clock(sih, si_osh(sih)); 1383 1384 return ALP_CLOCK; 1385} 1386 1387uint32 1388BCMINITFN(si_ilp_clock)(si_t *sih) 1389{ 1390 if (PMUCTL_ENAB(sih)) 1391 return si_pmu_ilp_clock(sih, si_osh(sih)); 1392 1393 return ILP_CLOCK; 1394} 1395 1396/* set chip watchdog reset timer to fire in 'ticks' */ 1397void 1398si_watchdog(si_t *sih, uint ticks) 1399{ 1400 uint nb, maxt; 1401 1402 if (PMUCTL_ENAB(sih)) { 1403 1404#if !defined(_CFE_) || defined(CFG_WL) 1405 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && 1406 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { 1407 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); 1408 si_setcore(sih, USB20D_CORE_ID, 0); 1409 si_core_disable(sih, 1); 1410 si_setcore(sih, CC_CORE_ID, 0); 1411 } 1412#endif /* !_CFE_ || CFG_WL */ 1413 1414 if (CHIPID(sih->chip) == BCM4706_CHIP_ID) 1415 nb = 32; 1416 else 1417 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); 1418 /* The mips compiler uses the sllv instruction, 1419 * so we specially handle the 32-bit case. 1420 */ 1421 if (nb == 32) 1422 maxt = 0xffffffff; 1423 else 1424 maxt = ((1 << nb) - 1); 1425 1426 if (ticks == 1) 1427 ticks = 2; 1428 else if (ticks > maxt) 1429 ticks = maxt; 1430 1431 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); 1432 } else { 1433 /* make sure we come up in fast clock mode; or if clearing, clear clock */ 1434 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC); 1435 maxt = (1 << 28) - 1; 1436 if (ticks > maxt) 1437 ticks = maxt; 1438 1439 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); 1440 } 1441} 1442 1443/* trigger watchdog reset after ms milliseconds */ 1444void 1445si_watchdog_ms(si_t *sih, uint32 ms) 1446{ 1447 si_watchdog(sih, wd_msticks * ms); 1448} 1449 1450#if defined(BCMASSERT_SUPPORT) || defined(BCMDBG_DUMP) 1451bool 1452si_taclear(si_t *sih, bool details) 1453{ 1454 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1455 return sb_taclear(sih, details); 1456 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1457 return FALSE; 1458 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1459 return FALSE; 1460 else { 1461 ASSERT(0); 1462 return FALSE; 1463 } 1464} 1465#endif 1466 1467uint16 1468BCMATTACHFN(si_d11_devid)(si_t *sih) 1469{ 1470 si_info_t *sii = SI_INFO(sih); 1471 uint16 device; 1472 1473 /* Fix device id for dual band BCM4328 */ 1474 if (CHIPID(sih->chip) == BCM4328_CHIP_ID && 1475 (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID)) 1476 device = BCM4328_D11DUAL_ID; 1477 else { 1478 /* normal case: nvram variable with devpath->devid->wl0id */ 1479 if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0) 1480 ; 1481 /* Get devid from OTP/SPROM depending on where the SROM is read */ 1482 else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0) 1483 ; 1484 /* no longer support wl0id, but keep the code here for backward compatibility. */ 1485 else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0) 1486 ; 1487 else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) { 1488 /* Chip specific conversion */ 1489 if (sih->chippkg == BCM4712SMALL_PKG_ID) 1490 device = BCM4306_D11G_ID; 1491 else 1492 device = BCM4306_D11DUAL_ID; 1493 } else { 1494 /* ignore it */ 1495 device = 0xffff; 1496 } 1497 } 1498 return device; 1499} 1500 1501int 1502BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice, 1503 uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, 1504 uint8 *pciheader) 1505{ 1506 uint16 vendor = 0xffff, device = 0xffff; 1507 uint8 class, subclass, progif = 0; 1508 uint8 header = PCI_HEADER_NORMAL; 1509 uint32 core = si_coreid(sih); 1510 1511 /* Verify whether the function exists for the core */ 1512 if (func >= (uint)(core == USB20H_CORE_ID ? 2 : 1)) 1513 return BCME_ERROR; 1514 1515 /* Known vendor translations */ 1516 switch (si_corevendor(sih)) { 1517 case SB_VEND_BCM: 1518 case MFGID_BRCM: 1519 vendor = VENDOR_BROADCOM; 1520 break; 1521 default: 1522 return BCME_ERROR; 1523 } 1524 1525 /* Determine class based on known core codes */ 1526 switch (core) { 1527 case ENET_CORE_ID: 1528 class = PCI_CLASS_NET; 1529 subclass = PCI_NET_ETHER; 1530 device = BCM47XX_ENET_ID; 1531 break; 1532 case GIGETH_CORE_ID: 1533 class = PCI_CLASS_NET; 1534 subclass = PCI_NET_ETHER; 1535 device = BCM47XX_GIGETH_ID; 1536 break; 1537 case GMAC_CORE_ID: 1538 class = PCI_CLASS_NET; 1539 subclass = PCI_NET_ETHER; 1540 device = BCM47XX_GMAC_ID; 1541 break; 1542 case SDRAM_CORE_ID: 1543 case MEMC_CORE_ID: 1544 case DMEMC_CORE_ID: 1545 case SOCRAM_CORE_ID: 1546 class = PCI_CLASS_MEMORY; 1547 subclass = PCI_MEMORY_RAM; 1548 device = (uint16)core; 1549 break; 1550 case PCI_CORE_ID: 1551 case PCIE_CORE_ID: 1552 class = PCI_CLASS_BRIDGE; 1553 subclass = PCI_BRIDGE_PCI; 1554 device = (uint16)core; 1555 header = PCI_HEADER_BRIDGE; 1556 break; 1557 case MIPS33_CORE_ID: 1558 case MIPS74K_CORE_ID: 1559 class = PCI_CLASS_CPU; 1560 subclass = PCI_CPU_MIPS; 1561 device = (uint16)core; 1562 break; 1563 case CODEC_CORE_ID: 1564 class = PCI_CLASS_COMM; 1565 subclass = PCI_COMM_MODEM; 1566 device = BCM47XX_V90_ID; 1567 break; 1568 case I2S_CORE_ID: 1569 class = PCI_CLASS_MMEDIA; 1570 subclass = PCI_MMEDIA_AUDIO; 1571 device = BCM47XX_AUDIO_ID; 1572 break; 1573 case USB_CORE_ID: 1574 case USB11H_CORE_ID: 1575 class = PCI_CLASS_SERIAL; 1576 subclass = PCI_SERIAL_USB; 1577 progif = 0x10; /* OHCI */ 1578 device = BCM47XX_USBH_ID; 1579 break; 1580 case USB20H_CORE_ID: 1581 class = PCI_CLASS_SERIAL; 1582 subclass = PCI_SERIAL_USB; 1583 progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */ 1584 device = BCM47XX_USB20H_ID; 1585 header = 0x80; /* multifunction */ 1586 break; 1587 case IPSEC_CORE_ID: 1588 class = PCI_CLASS_CRYPT; 1589 subclass = PCI_CRYPT_NETWORK; 1590 device = BCM47XX_IPSEC_ID; 1591 break; 1592 case ROBO_CORE_ID: 1593 /* Don't use class NETWORK, so wl/et won't attempt to recognize it */ 1594 class = PCI_CLASS_COMM; 1595 subclass = PCI_COMM_OTHER; 1596 device = BCM47XX_ROBO_ID; 1597 break; 1598 case CC_CORE_ID: 1599 class = PCI_CLASS_MEMORY; 1600 subclass = PCI_MEMORY_FLASH; 1601 device = (uint16)core; 1602 break; 1603 case SATAXOR_CORE_ID: 1604 class = PCI_CLASS_XOR; 1605 subclass = PCI_XOR_QDMA; 1606 device = BCM47XX_SATAXOR_ID; 1607 break; 1608 case ATA100_CORE_ID: 1609 class = PCI_CLASS_DASDI; 1610 subclass = PCI_DASDI_IDE; 1611 device = BCM47XX_ATA100_ID; 1612 break; 1613 case USB11D_CORE_ID: 1614 class = PCI_CLASS_SERIAL; 1615 subclass = PCI_SERIAL_USB; 1616 device = BCM47XX_USBD_ID; 1617 break; 1618 case USB20D_CORE_ID: 1619 class = PCI_CLASS_SERIAL; 1620 subclass = PCI_SERIAL_USB; 1621 device = BCM47XX_USB20D_ID; 1622 break; 1623 case D11_CORE_ID: 1624 class = PCI_CLASS_NET; 1625 subclass = PCI_NET_OTHER; 1626 device = si_d11_devid(sih); 1627 break; 1628 1629 default: 1630 class = subclass = progif = 0xff; 1631 device = (uint16)core; 1632 break; 1633 } 1634 1635 *pcivendor = vendor; 1636 *pcidevice = device; 1637 *pciclass = class; 1638 *pcisubclass = subclass; 1639 *pciprogif = progif; 1640 *pciheader = header; 1641 1642 return 0; 1643} 1644 1645#if defined(BCMDBG_DUMP) 1646/* print interesting sbconfig registers */ 1647void 1648si_dumpregs(si_t *sih, struct bcmstrbuf *b) 1649{ 1650 si_info_t *sii; 1651 uint origidx, intr_val = 0; 1652 1653 sii = SI_INFO(sih); 1654 origidx = sii->curidx; 1655 1656 INTR_OFF(sii, intr_val); 1657 if (CHIPTYPE(sih->socitype) == SOCI_SB) 1658 sb_dumpregs(sih, b); 1659 else if (CHIPTYPE(sih->socitype) == SOCI_AI) 1660 ai_dumpregs(sih, b); 1661 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) 1662 ub_dumpregs(sih, b); 1663 else 1664 ASSERT(0); 1665 1666 si_setcoreidx(sih, origidx); 1667 INTR_RESTORE(sii, intr_val); 1668} 1669#endif 1670 1671 1672/* return the slow clock source - LPO, XTAL, or PCI */ 1673static uint 1674si_slowclk_src(si_info_t *sii) 1675{ 1676 chipcregs_t *cc; 1677 1678 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1679 1680 if (sii->pub.ccrev < 6) { 1681 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && 1682 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & 1683 PCI_CFG_GPIO_SCS)) 1684 return (SCC_SS_PCI); 1685 else 1686 return (SCC_SS_XTAL); 1687 } else if (sii->pub.ccrev < 10) { 1688 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); 1689 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); 1690 } else /* Insta-clock */ 1691 return (SCC_SS_XTAL); 1692} 1693 1694/* return the ILP (slowclock) min or max frequency */ 1695static uint 1696si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) 1697{ 1698 uint32 slowclk; 1699 uint div; 1700 1701 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); 1702 1703 /* shouldn't be here unless we've established the chip has dynamic clk control */ 1704 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); 1705 1706 slowclk = si_slowclk_src(sii); 1707 if (sii->pub.ccrev < 6) { 1708 if (slowclk == SCC_SS_PCI) 1709 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); 1710 else 1711 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); 1712 } else if (sii->pub.ccrev < 10) { 1713 div = 4 * 1714 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); 1715 if (slowclk == SCC_SS_LPO) 1716 return (max_freq ? LPOMAXFREQ : LPOMINFREQ); 1717 else if (slowclk == SCC_SS_XTAL) 1718 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); 1719 else if (slowclk == SCC_SS_PCI) 1720 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); 1721 else 1722 ASSERT(0); 1723 } else { 1724 /* Chipc rev 10 is InstaClock */ 1725 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; 1726 div = 4 * (div + 1); 1727 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); 1728 } 1729 return (0); 1730} 1731 1732static void 1733BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs) 1734{ 1735 chipcregs_t *cc = (chipcregs_t *)chipcregs; 1736 uint slowmaxfreq, pll_delay, slowclk; 1737 uint pll_on_delay, fref_sel_delay; 1738 1739 pll_delay = PLL_DELAY; 1740 1741 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay 1742 * since the xtal will also be powered down by dynamic clk control logic. 1743 */ 1744 1745 slowclk = si_slowclk_src(sii); 1746 if (slowclk != SCC_SS_XTAL) 1747 pll_delay += XTAL_ON_DELAY; 1748 1749 /* Starting with 4318 it is ILP that is used for the delays */ 1750 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); 1751 1752 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; 1753 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; 1754 1755 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); 1756 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); 1757} 1758 1759/* initialize power control delay registers */ 1760void 1761BCMINITFN(si_clkctl_init)(si_t *sih) 1762{ 1763 si_info_t *sii; 1764 uint origidx = 0; 1765 chipcregs_t *cc; 1766 bool fast; 1767 1768 if (!CCCTL_ENAB(sih)) 1769 return; 1770 1771 sii = SI_INFO(sih); 1772 fast = SI_FAST(sii); 1773 if (!fast) { 1774 origidx = sii->curidx; 1775 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 1776 return; 1777 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 1778 return; 1779 ASSERT(cc != NULL); 1780 1781 /* set all Instaclk chip ILP to 1 MHz */ 1782 if (sih->ccrev >= 10) 1783 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, 1784 (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); 1785 1786 si_clkctl_setdelay(sii, (void *)(uintptr)cc); 1787 1788 if (!fast) 1789 si_setcoreidx(sih, origidx); 1790} 1791 1792/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */ 1793uint16 1794BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih) 1795{ 1796 si_info_t *sii; 1797 uint origidx = 0; 1798 chipcregs_t *cc; 1799 uint slowminfreq; 1800 uint16 fpdelay; 1801 uint intr_val = 0; 1802 bool fast; 1803 1804 sii = SI_INFO(sih); 1805 if (PMUCTL_ENAB(sih)) { 1806 INTR_OFF(sii, intr_val); 1807 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh); 1808 INTR_RESTORE(sii, intr_val); 1809 return fpdelay; 1810 } 1811 1812 if (!CCCTL_ENAB(sih)) 1813 return 0; 1814 1815 fast = SI_FAST(sii); 1816 fpdelay = 0; 1817 if (!fast) { 1818 origidx = sii->curidx; 1819 INTR_OFF(sii, intr_val); 1820 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 1821 goto done; 1822 } 1823 else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 1824 goto done; 1825 ASSERT(cc != NULL); 1826 1827 slowminfreq = si_slowclk_freq(sii, FALSE, cc); 1828 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) + 1829 (slowminfreq - 1)) / slowminfreq; 1830 1831done: 1832 if (!fast) { 1833 si_setcoreidx(sih, origidx); 1834 INTR_RESTORE(sii, intr_val); 1835 } 1836 return fpdelay; 1837} 1838 1839/* turn primary xtal and/or pll off/on */ 1840int 1841si_clkctl_xtal(si_t *sih, uint what, bool on) 1842{ 1843 si_info_t *sii; 1844 uint32 in, out, outen; 1845 1846 sii = SI_INFO(sih); 1847 1848 switch (BUSTYPE(sih->bustype)) { 1849 1850 1851 case PCMCIA_BUS: 1852 return (0); 1853 1854 1855 case PCI_BUS: 1856 /* pcie core doesn't have any mapping to control the xtal pu */ 1857 if (PCIE(sii)) 1858 return -1; 1859 1860 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32)); 1861 out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)); 1862 outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32)); 1863 1864 /* 1865 * Avoid glitching the clock if GPRS is already using it. 1866 * We can't actually read the state of the PLLPD so we infer it 1867 * by the value of XTAL_PU which *is* readable via gpioin. 1868 */ 1869 if (on && (in & PCI_CFG_GPIO_XTAL)) 1870 return (0); 1871 1872 if (what & XTAL) 1873 outen |= PCI_CFG_GPIO_XTAL; 1874 if (what & PLL) 1875 outen |= PCI_CFG_GPIO_PLL; 1876 1877 if (on) { 1878 /* turn primary xtal on */ 1879 if (what & XTAL) { 1880 out |= PCI_CFG_GPIO_XTAL; 1881 if (what & PLL) 1882 out |= PCI_CFG_GPIO_PLL; 1883 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, 1884 sizeof(uint32), out); 1885 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, 1886 sizeof(uint32), outen); 1887 OSL_DELAY(XTAL_ON_DELAY); 1888 } 1889 1890 /* turn pll on */ 1891 if (what & PLL) { 1892 out &= ~PCI_CFG_GPIO_PLL; 1893 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, 1894 sizeof(uint32), out); 1895 OSL_DELAY(2000); 1896 } 1897 } else { 1898 if (what & XTAL) 1899 out &= ~PCI_CFG_GPIO_XTAL; 1900 if (what & PLL) 1901 out |= PCI_CFG_GPIO_PLL; 1902 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out); 1903 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32), 1904 outen); 1905 } 1906 return (0); 1907 default: 1908 return (-1); 1909 } 1910} 1911 1912/* 1913 * clock control policy function throught chipcommon 1914 * 1915 * set dynamic clk control mode (forceslow, forcefast, dynamic) 1916 * returns true if we are forcing fast clock 1917 * this is a wrapper over the next internal function 1918 * to allow flexible policy settings for outside caller 1919 */ 1920bool 1921si_clkctl_cc(si_t *sih, uint mode) 1922{ 1923 si_info_t *sii; 1924 1925 sii = SI_INFO(sih); 1926 1927 /* chipcommon cores prior to rev6 don't support dynamic clock control */ 1928 if (sih->ccrev < 6) 1929 return FALSE; 1930 1931 if (PCI_FORCEHT(sii)) 1932 return (mode == CLK_FAST); 1933 1934 return _si_clkctl_cc(sii, mode); 1935} 1936 1937/* clk control mechanism through chipcommon, no policy checking */ 1938static bool 1939_si_clkctl_cc(si_info_t *sii, uint mode) 1940{ 1941 uint origidx = 0; 1942 chipcregs_t *cc; 1943 uint32 scc; 1944 uint intr_val = 0; 1945 bool fast = SI_FAST(sii); 1946 1947 /* chipcommon cores prior to rev6 don't support dynamic clock control */ 1948 if (sii->pub.ccrev < 6) 1949 return (FALSE); 1950 1951 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ 1952 ASSERT(sii->pub.ccrev != 10); 1953 1954 if (!fast) { 1955 INTR_OFF(sii, intr_val); 1956 origidx = sii->curidx; 1957 1958 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && 1959 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) && 1960 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) 1961 goto done; 1962 1963 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0); 1964 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL) 1965 goto done; 1966 ASSERT(cc != NULL); 1967 1968 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20)) 1969 goto done; 1970 1971 switch (mode) { 1972 case CLK_FAST: /* FORCEHT, fast (pll) clock */ 1973 if (sii->pub.ccrev < 10) { 1974 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ 1975 si_clkctl_xtal(&sii->pub, XTAL, ON); 1976 SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); 1977 } else if (sii->pub.ccrev < 20) { 1978 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR); 1979 } else { 1980 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT); 1981 } 1982 1983 /* wait for the PLL */ 1984 if (PMUCTL_ENAB(&sii->pub)) { 1985 uint32 htavail = CCS_HTAVAIL; 1986 if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID) 1987 htavail = CCS0_HTAVAIL; 1988 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0), 1989 PMU_MAX_TRANSITION_DLY); 1990 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail); 1991 } else { 1992 OSL_DELAY(PLL_DELAY); 1993 } 1994 break; 1995 1996 case CLK_DYNAMIC: /* enable dynamic clock control */ 1997 if (sii->pub.ccrev < 10) { 1998 scc = R_REG(sii->osh, &cc->slow_clk_ctl); 1999 scc &= ~(SCC_FS | SCC_IP | SCC_XC); 2000 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) 2001 scc |= SCC_XC; 2002 W_REG(sii->osh, &cc->slow_clk_ctl, scc); 2003 2004 /* for dynamic control, we have to release our xtal_pu "force on" */ 2005 if (scc & SCC_XC) 2006 si_clkctl_xtal(&sii->pub, XTAL, OFF); 2007 } else if (sii->pub.ccrev < 20) { 2008 /* Instaclock */ 2009 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR); 2010 } else { 2011 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); 2012 } 2013 break; 2014 2015 default: 2016 ASSERT(0); 2017 } 2018 2019done: 2020 if (!fast) { 2021 si_setcoreidx(&sii->pub, origidx); 2022 INTR_RESTORE(sii, intr_val); 2023 } 2024 return (mode == CLK_FAST); 2025} 2026 2027/* Build device path. Support SI, PCI, and JTAG for now. */ 2028int 2029BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size) 2030{ 2031 int slen; 2032 2033 ASSERT(path != NULL); 2034 ASSERT(size >= SI_DEVPATH_BUFSZ); 2035 2036 if (!path || size <= 0) 2037 return -1; 2038 2039 switch (BUSTYPE(sih->bustype)) { 2040 case SI_BUS: 2041 case JTAG_BUS: 2042 slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih)); 2043 break; 2044 case PCI_BUS: 2045 ASSERT((SI_INFO(sih))->osh != NULL); 2046 slen = snprintf(path, (size_t)size, "pci/%u/%u/", 2047 OSL_PCI_BUS((SI_INFO(sih))->osh), 2048 OSL_PCI_SLOT((SI_INFO(sih))->osh)); 2049 break; 2050 case PCMCIA_BUS: 2051 SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n")); 2052 SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n")); 2053 slen = snprintf(path, (size_t)size, "pc/1/1/"); 2054 break; 2055 default: 2056 slen = -1; 2057 ASSERT(0); 2058 break; 2059 } 2060 2061 if (slen < 0 || slen >= size) { 2062 path[0] = '\0'; 2063 return -1; 2064 } 2065 2066 return 0; 2067} 2068 2069char * 2070BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name) 2071{ 2072 char pathname[SI_DEVPATH_BUFSZ + 32]; 2073 char devpath[SI_DEVPATH_BUFSZ + 32]; 2074 char *p; 2075 int idx; 2076 int len; 2077 2078 /* try to get compact devpath if it exist */ 2079 if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) { 2080 len = strlen(devpath); 2081 devpath[len - 1] = '\0'; 2082 for (idx = 0; idx < SI_MAXCORES; idx++) { 2083 snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx); 2084 if ((p = getvar(NULL, pathname)) == NULL) 2085 continue; 2086 2087 if (strncmp(p, devpath, len) == 0) { 2088 snprintf(varname, var_len, "%d:%s", idx, name); 2089 return varname; 2090 } 2091 } 2092 } 2093 2094 return NULL; 2095} 2096 2097/* Get a variable, but only if it has a devpath prefix */ 2098char * 2099BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name) 2100{ 2101 char varname[SI_DEVPATH_BUFSZ + 32]; 2102 char *val; 2103 2104 si_devpathvar(sih, varname, sizeof(varname), name); 2105 2106 if ((val = getvar(NULL, varname)) != NULL) 2107 return val; 2108 2109 /* try to get compact devpath if it exist */ 2110 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) 2111 return NULL; 2112 2113 return (getvar(NULL, varname)); 2114} 2115 2116/* Get a variable, but only if it has a devpath prefix */ 2117int 2118BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name) 2119{ 2120#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) 2121 return (getintvar(NULL, name)); 2122#else 2123 char varname[SI_DEVPATH_BUFSZ + 32]; 2124 int val; 2125 2126 si_devpathvar(sih, varname, sizeof(varname), name); 2127 2128 if ((val = getintvar(NULL, varname)) != 0) 2129 return val; 2130 2131 /* try to get compact devpath if it exist */ 2132 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) 2133 return 0; 2134 2135 return (getintvar(NULL, varname)); 2136#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */ 2137} 2138 2139#ifndef DONGLEBUILD 2140char * 2141si_getnvramflvar(si_t *sih, const char *name) 2142{ 2143 return (getvar(NULL, name)); 2144} 2145#endif /* DONGLEBUILD */ 2146 2147/* Concatenate the dev path with a varname into the given 'var' buffer 2148 * and return the 'var' pointer. 2149 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. 2150 * On overflow, the first char will be set to '\0'. 2151 */ 2152static char * 2153BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name) 2154{ 2155 uint path_len; 2156 2157 if (!var || len <= 0) 2158 return var; 2159 2160 if (si_devpath(sih, var, len) == 0) { 2161 path_len = strlen(var); 2162 2163 if (strlen(name) + 1 > (uint)(len - path_len)) 2164 var[0] = '\0'; 2165 else 2166 strncpy(var + path_len, name, len - path_len - 1); 2167 } 2168 2169 return var; 2170} 2171 2172 2173uint32 2174si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type) 2175{ 2176 si_info_t *sii; 2177 2178 sii = SI_INFO(sih); 2179 2180 if (!PCIE(sii)) { 2181 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__)); 2182 return 0; 2183 } 2184 2185 return pcicore_pciereg(sii->pch, offset, mask, val, type); 2186} 2187 2188uint32 2189si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val) 2190{ 2191 si_info_t *sii; 2192 2193 sii = SI_INFO(sih); 2194 2195 if (!PCIE(sii)) { 2196 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__)); 2197 return 0; 2198 } 2199 2200 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val); 2201 2202} 2203 2204/* return TRUE if PCIE capability exists in the pci config space */ 2205static bool 2206si_ispcie(si_info_t *sii) 2207{ 2208 uint8 cap_ptr; 2209 2210 if (BUSTYPE(sii->pub.bustype) != PCI_BUS) 2211 return FALSE; 2212 2213 cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL); 2214 if (!cap_ptr) 2215 return FALSE; 2216 2217 return TRUE; 2218} 2219 2220/* Wake-on-wireless-LAN (WOWL) support functions */ 2221/* Enable PME generation and disable clkreq */ 2222void 2223si_pci_pmeen(si_t *sih) 2224{ 2225 si_info_t *sii; 2226 2227 sii = SI_INFO(sih); 2228 2229 pcicore_pmeen(sii->pch); 2230} 2231 2232/* Return TRUE if PME status is set */ 2233bool 2234si_pci_pmestat(si_t *sih) 2235{ 2236 si_info_t *sii; 2237 2238 sii = SI_INFO(sih); 2239 2240 return pcicore_pmestat(sii->pch); 2241} 2242 2243/* Disable PME generation, clear the PME status bit if set */ 2244void 2245si_pci_pmeclr(si_t *sih) 2246{ 2247 si_info_t *sii; 2248 2249 sii = SI_INFO(sih); 2250 2251 pcicore_pmeclr(sii->pch); 2252} 2253 2254/* initialize the pcmcia core */ 2255void 2256si_pcmcia_init(si_t *sih) 2257{ 2258 si_info_t *sii; 2259 uint8 cor = 0; 2260 2261 sii = SI_INFO(sih); 2262 2263 /* enable d11 mac interrupts */ 2264 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); 2265 cor |= COR_IRQEN | COR_FUNEN; 2266 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1); 2267 2268} 2269 2270 2271bool 2272BCMATTACHFN(si_pci_war16165)(si_t *sih) 2273{ 2274 si_info_t *sii; 2275 2276 sii = SI_INFO(sih); 2277 2278 return (PCI(sii) && (sih->buscorerev <= 10)); 2279} 2280 2281/* Disable pcie_war_ovr for some platforms (sigh!) 2282 * This is for boards that have BFL2_PCIEWAR_OVR set 2283 * but are in systems that still want the benefits of ASPM 2284 * Note that this should be done AFTER si_doattach 2285 */ 2286void 2287si_pcie_war_ovr_update(si_t *sih, uint8 aspm) 2288{ 2289 si_info_t *sii; 2290 2291 sii = SI_INFO(sih); 2292 2293 if (!PCIE(sii)) 2294 return; 2295 2296 pcie_war_ovr_aspm_update(sii->pch, aspm); 2297} 2298 2299void 2300si_pcie_power_save_enable(si_t *sih, bool enable) 2301{ 2302 si_info_t *sii; 2303 2304 sii = SI_INFO(sih); 2305 2306 if (!PCIE(sii)) 2307 return; 2308 2309 pcie_power_save_enable(sii->pch, enable); 2310} 2311 2312void 2313si_pcie_set_request_size(si_t *sih, uint16 size) 2314{ 2315 si_info_t *sii; 2316 2317 sii = SI_INFO(sih); 2318 2319 if (!PCIE(sii)) 2320 return; 2321 2322 pcie_set_request_size(sii->pch, size); 2323} 2324 2325uint16 2326si_pcie_get_request_size(si_t *sih) 2327{ 2328 si_info_t *sii; 2329 2330 sii = SI_INFO(sih); 2331 2332 if (!PCIE(sii)) 2333 return (0); 2334 2335 return pcie_get_request_size(sii->pch); 2336} 2337 2338/* back door for other module to override chippkg */ 2339void 2340si_chippkg_set(si_t *sih, uint val) 2341{ 2342 si_info_t *sii; 2343 2344 sii = SI_INFO(sih); 2345 2346 sii->pub.chippkg = val; 2347} 2348 2349void 2350BCMINITFN(si_pci_up)(si_t *sih) 2351{ 2352 si_info_t *sii; 2353 2354 sii = SI_INFO(sih); 2355 2356 /* if not pci bus, we're done */ 2357 if (BUSTYPE(sih->bustype) != PCI_BUS) 2358 return; 2359 2360 if (PCI_FORCEHT(sii)) 2361 _si_clkctl_cc(sii, CLK_FAST); 2362 2363 if (PCIE(sii)) { 2364 pcicore_up(sii->pch, SI_PCIUP); 2365 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) || 2366 (CHIPID(sih->chip) == BCM4312_CHIP_ID)) 2367 sb_set_initiator_to((void *)sii, 0x3, 2368 si_findcoreidx((void *)sii, D11_CORE_ID, 0)); 2369 } 2370} 2371 2372/* Unconfigure and/or apply various WARs when system is going to sleep mode */ 2373void 2374BCMUNINITFN(si_pci_sleep)(si_t *sih) 2375{ 2376 si_info_t *sii; 2377 2378 sii = SI_INFO(sih); 2379 2380 pcicore_sleep(sii->pch); 2381} 2382 2383/* Unconfigure and/or apply various WARs when going down */ 2384void 2385BCMINITFN(si_pci_down)(si_t *sih) 2386{ 2387 si_info_t *sii; 2388 2389 sii = SI_INFO(sih); 2390 2391 /* if not pci bus, we're done */ 2392 if (BUSTYPE(sih->bustype) != PCI_BUS) 2393 return; 2394 2395 /* release FORCEHT since chip is going to "down" state */ 2396 if (PCI_FORCEHT(sii)) 2397 _si_clkctl_cc(sii, CLK_DYNAMIC); 2398 2399 pcicore_down(sii->pch, SI_PCIDOWN); 2400} 2401 2402/* 2403 * Configure the pci core for pci client (NIC) action 2404 * coremask is the bitvec of cores by index to be enabled. 2405 */ 2406void 2407BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask) 2408{ 2409 si_info_t *sii; 2410 sbpciregs_t *pciregs = NULL; 2411 uint32 siflag = 0, w; 2412 uint idx = 0; 2413 2414 sii = SI_INFO(sih); 2415 2416 if (BUSTYPE(sii->pub.bustype) != PCI_BUS) 2417 return; 2418 2419 ASSERT(PCI(sii) || PCIE(sii)); 2420 ASSERT(sii->pub.buscoreidx != BADIDX); 2421 2422 if (PCI(sii)) { 2423 /* get current core index */ 2424 idx = sii->curidx; 2425 2426 /* we interrupt on this backplane flag number */ 2427 siflag = si_flag(sih); 2428 2429 /* switch over to pci core */ 2430 pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx); 2431 } 2432 2433 /* 2434 * Enable sb->pci interrupts. Assume 2435 * PCI rev 2.3 support was added in pci core rev 6 and things changed.. 2436 */ 2437 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) { 2438 /* pci config write to set this core bit in PCIIntMask */ 2439 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32)); 2440 w |= (coremask << PCI_SBIM_SHIFT); 2441#ifdef USER_MODE 2442 /* User mode operate with interrupt disabled */ 2443 w &= !(coremask << PCI_SBIM_SHIFT); 2444#endif 2445 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w); 2446 } else { 2447 /* set sbintvec bit for our flag number */ 2448 si_setint(sih, siflag); 2449 } 2450 2451 if (PCI(sii)) { 2452 OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST)); 2453 if (sii->pub.buscorerev >= 11) { 2454 OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI); 2455 w = R_REG(sii->osh, &pciregs->clkrun); 2456 W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL)); 2457 w = R_REG(sii->osh, &pciregs->clkrun); 2458 } 2459 2460 /* switch back to previous core */ 2461 si_setcoreidx(sih, idx); 2462 } 2463} 2464 2465uint8 2466si_pcieclkreq(si_t *sih, uint32 mask, uint32 val) 2467{ 2468 si_info_t *sii; 2469 2470 sii = SI_INFO(sih); 2471 2472 if (!(PCIE(sii))) 2473 return 0; 2474 return pcie_clkreq(sii->pch, mask, val); 2475} 2476 2477uint32 2478si_pcielcreg(si_t *sih, uint32 mask, uint32 val) 2479{ 2480 si_info_t *sii; 2481 2482 sii = SI_INFO(sih); 2483 2484 if (!PCIE(sii)) 2485 return 0; 2486 2487 return pcie_lcreg(sii->pch, mask, val); 2488} 2489 2490/* indirect way to read pcie config regs */ 2491uint 2492si_pcie_readreg(void *sih, uint addrtype, uint offset) 2493{ 2494 return pcie_readreg(((si_info_t *)sih)->osh, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)), 2495 addrtype, offset); 2496} 2497 2498 2499/* 2500 * Fixup SROMless PCI device's configuration. 2501 * The current core may be changed upon return. 2502 */ 2503int 2504si_pci_fixcfg(si_t *sih) 2505{ 2506 uint origidx, pciidx; 2507 sbpciregs_t *pciregs = NULL; 2508 sbpcieregs_t *pcieregs = NULL; 2509 void *regs = NULL; 2510 uint16 val16, *reg16 = NULL; 2511 uint32 w; 2512 2513 si_info_t *sii = SI_INFO(sih); 2514 2515 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS); 2516 2517 if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) { 2518 w = (CHIPREV(sii->pub.chiprev) == 0) ? 2519 CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT; 2520 si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w); 2521 } 2522 2523 /* Fixup PI in SROM shadow area to enable the correct PCI core access */ 2524 /* save the current index */ 2525 origidx = si_coreidx(&sii->pub); 2526 2527 /* check 'pi' is correct and fix it if not */ 2528 if (sii->pub.buscoretype == PCIE_CORE_ID) { 2529 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0); 2530 regs = pcieregs; 2531 ASSERT(pcieregs != NULL); 2532 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; 2533 } else if (sii->pub.buscoretype == PCI_CORE_ID) { 2534 pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0); 2535 regs = pciregs; 2536 ASSERT(pciregs != NULL); 2537 reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; 2538 } 2539 pciidx = si_coreidx(&sii->pub); 2540 val16 = R_REG(sii->osh, reg16); 2541 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) { 2542 val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK); 2543 W_REG(sii->osh, reg16, val16); 2544 } 2545 2546 /* restore the original index */ 2547 si_setcoreidx(&sii->pub, origidx); 2548 2549 pcicore_hwup(sii->pch); 2550 return 0; 2551} 2552 2553#if defined(BCMDBG_DUMP) 2554 2555void 2556si_dump(si_t *sih, struct bcmstrbuf *b) 2557{ 2558 si_info_t *sii; 2559 uint i; 2560 2561 sii = SI_INFO(sih); 2562 2563 bcm_bprintf(b, "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n", 2564 sii, sih->chip, sih->chiprev, sih->boardtype, sih->boardvendor, sih->bustype); 2565 bcm_bprintf(b, "osh %p curmap %p\n", 2566 sii->osh, sii->curmap); 2567 if (CHIPTYPE(sih->socitype) == SOCI_SB) 2568 bcm_bprintf(b, "sonicsrev %d ", sih->socirev); 2569 bcm_bprintf(b, "ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n", 2570 sih->ccrev, sih->buscoretype, sih->buscorerev, sii->curidx); 2571 2572 2573 bcm_bprintf(b, "cores: "); 2574 for (i = 0; i < sii->numcores; i++) 2575 bcm_bprintf(b, "0x%x ", sii->coreid[i]); 2576 bcm_bprintf(b, "\n"); 2577} 2578 2579void 2580si_ccreg_dump(si_t *sih, struct bcmstrbuf *b) 2581{ 2582 si_info_t *sii; 2583 uint origidx; 2584 uint i, intr_val = 0; 2585 chipcregs_t *cc; 2586 2587 sii = SI_INFO(sih); 2588 origidx = sii->curidx; 2589 2590 /* only support corerev 22 for now */ 2591 if (sih->ccrev != 23) 2592 return; 2593 2594 INTR_OFF(sii, intr_val); 2595 2596 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2597 2598 bcm_bprintf(b, "\n===cc(rev %d) registers(offset val)===\n", sih->ccrev); 2599 for (i = 0; i <= 0xc4; i += 4) { 2600 if (i == 0x4c) { 2601 bcm_bprintf(b, "\n"); 2602 continue; 2603 } 2604 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i)); 2605 } 2606 2607 bcm_bprintf(b, "\n"); 2608 2609 for (i = 0x1e0; i <= 0x1e4; i += 4) { 2610 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i)); 2611 } 2612 bcm_bprintf(b, "\n"); 2613 2614 if (sih->cccaps & CC_CAP_PMU) { 2615 for (i = 0x600; i <= 0x660; i += 4) { 2616 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i)); 2617 } 2618 } 2619 bcm_bprintf(b, "\n"); 2620 2621 si_setcoreidx(sih, origidx); 2622 INTR_RESTORE(sii, intr_val); 2623} 2624 2625/* dump dynamic clock control related registers */ 2626void 2627si_clkctl_dump(si_t *sih, struct bcmstrbuf *b) 2628{ 2629 si_info_t *sii; 2630 chipcregs_t *cc; 2631 uint origidx; 2632 uint intr_val = 0; 2633 2634 if (!(sih->cccaps & CC_CAP_PWR_CTL)) 2635 return; 2636 2637 sii = SI_INFO(sih); 2638 INTR_OFF(sii, intr_val); 2639 origidx = sii->curidx; 2640 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 2641 goto done; 2642 2643 bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ", 2644 cc->pll_on_delay, cc->fref_sel_delay); 2645 if ((sih->ccrev >= 6) && (sih->ccrev < 10)) 2646 bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl); 2647 if (sih->ccrev >= 10) { 2648 bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl); 2649 bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch); 2650 } 2651 2652 if (BUSTYPE(sih->bustype) == PCI_BUS) 2653 bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ", 2654 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)), 2655 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32))); 2656 2657 if (sih->cccaps & CC_CAP_PMU) { 2658 /* dump some PMU register ? */ 2659 } 2660 bcm_bprintf(b, "\n"); 2661 2662 si_setcoreidx(sih, origidx); 2663done: 2664 INTR_RESTORE(sii, intr_val); 2665} 2666 2667int 2668si_dump_pcieregs(si_t *sih, struct bcmstrbuf *b) 2669{ 2670 si_info_t *sii; 2671 2672 sii = SI_INFO(sih); 2673 2674 if (!PCIE(sii)) 2675 return BCME_ERROR; 2676 2677 return pcicore_dump_pcieregs(sii->pch, b); 2678} 2679 2680int 2681si_gpiodump(si_t *sih, struct bcmstrbuf *b) 2682{ 2683 si_info_t *sii; 2684 uint origidx; 2685 uint intr_val = 0; 2686 chipcregs_t *cc; 2687 2688 sii = SI_INFO(sih); 2689 2690 INTR_OFF(sii, intr_val); 2691 2692 origidx = si_coreidx(sih); 2693 2694 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 2695 ASSERT(cc); 2696 2697 bcm_bprintf(b, "GPIOregs\t"); 2698 2699 bcm_bprintf(b, "gpioin 0x%x ", R_REG(sii->osh, &cc->gpioin)); 2700 bcm_bprintf(b, "gpioout 0x%x ", R_REG(sii->osh, &cc->gpioout)); 2701 bcm_bprintf(b, "gpioouten 0x%x ", R_REG(sii->osh, &cc->gpioouten)); 2702 bcm_bprintf(b, "gpiocontrol 0x%x ", R_REG(sii->osh, &cc->gpiocontrol)); 2703 bcm_bprintf(b, "gpiointpolarity 0x%x ", R_REG(sii->osh, &cc->gpiointpolarity)); 2704 bcm_bprintf(b, "gpiointmask 0x%x ", R_REG(sii->osh, &cc->gpiointmask)); 2705 2706 if (sii->pub.ccrev >= 16) { 2707 bcm_bprintf(b, "gpiotimerval 0x%x ", R_REG(sii->osh, &cc->gpiotimerval)); 2708 bcm_bprintf(b, "gpiotimeroutmask 0x%x", R_REG(sii->osh, &cc->gpiotimeroutmask)); 2709 } 2710 bcm_bprintf(b, "\n"); 2711 2712 /* restore the original index */ 2713 si_setcoreidx(sih, origidx); 2714 2715 INTR_RESTORE(sii, intr_val); 2716 return 0; 2717 2718} 2719#endif 2720 2721/* change logical "focus" to the gpio core for optimized access */ 2722void * 2723si_gpiosetcore(si_t *sih) 2724{ 2725 return (si_setcoreidx(sih, SI_CC_IDX)); 2726} 2727 2728/* mask&set gpiocontrol bits */ 2729uint32 2730si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) 2731{ 2732 uint regoff; 2733 2734 regoff = 0; 2735 2736 /* gpios could be shared on router platforms 2737 * ignore reservation if it's high priority (e.g., test apps) 2738 */ 2739 if ((priority != GPIO_HI_PRIORITY) && 2740 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 2741 mask = priority ? (si_gpioreservation & mask) : 2742 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 2743 val &= mask; 2744 } 2745 2746 regoff = OFFSETOF(chipcregs_t, gpiocontrol); 2747 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 2748} 2749 2750/* mask&set gpio output enable bits */ 2751uint32 2752si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) 2753{ 2754 uint regoff; 2755 2756 regoff = 0; 2757 2758 /* gpios could be shared on router platforms 2759 * ignore reservation if it's high priority (e.g., test apps) 2760 */ 2761 if ((priority != GPIO_HI_PRIORITY) && 2762 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 2763 mask = priority ? (si_gpioreservation & mask) : 2764 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 2765 val &= mask; 2766 } 2767 2768 regoff = OFFSETOF(chipcregs_t, gpioouten); 2769 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 2770} 2771 2772/* mask&set gpio output bits */ 2773uint32 2774si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) 2775{ 2776 uint regoff; 2777 2778 regoff = 0; 2779 2780 /* gpios could be shared on router platforms 2781 * ignore reservation if it's high priority (e.g., test apps) 2782 */ 2783 if ((priority != GPIO_HI_PRIORITY) && 2784 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 2785 mask = priority ? (si_gpioreservation & mask) : 2786 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 2787 val &= mask; 2788 } 2789 2790 regoff = OFFSETOF(chipcregs_t, gpioout); 2791 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 2792} 2793 2794/* reserve one gpio */ 2795uint32 2796si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) 2797{ 2798 si_info_t *sii; 2799 2800 sii = SI_INFO(sih); 2801 2802 /* only cores on SI_BUS share GPIO's and only applcation users need to 2803 * reserve/release GPIO 2804 */ 2805 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 2806 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 2807 return 0xffffffff; 2808 } 2809 /* make sure only one bit is set */ 2810 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 2811 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 2812 return 0xffffffff; 2813 } 2814 2815 /* already reserved */ 2816 if (si_gpioreservation & gpio_bitmask) 2817 return 0xffffffff; 2818 /* set reservation */ 2819 si_gpioreservation |= gpio_bitmask; 2820 2821 return si_gpioreservation; 2822} 2823 2824/* release one gpio */ 2825/* 2826 * releasing the gpio doesn't change the current value on the GPIO last write value 2827 * persists till some one overwrites it 2828 */ 2829 2830uint32 2831si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) 2832{ 2833 si_info_t *sii; 2834 2835 sii = SI_INFO(sih); 2836 2837 /* only cores on SI_BUS share GPIO's and only applcation users need to 2838 * reserve/release GPIO 2839 */ 2840 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { 2841 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); 2842 return 0xffffffff; 2843 } 2844 /* make sure only one bit is set */ 2845 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { 2846 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); 2847 return 0xffffffff; 2848 } 2849 2850 /* already released */ 2851 if (!(si_gpioreservation & gpio_bitmask)) 2852 return 0xffffffff; 2853 2854 /* clear reservation */ 2855 si_gpioreservation &= ~gpio_bitmask; 2856 2857 return si_gpioreservation; 2858} 2859 2860/* return the current gpioin register value */ 2861uint32 2862si_gpioin(si_t *sih) 2863{ 2864 si_info_t *sii; 2865 uint regoff; 2866 2867 sii = SI_INFO(sih); 2868 regoff = 0; 2869 2870 regoff = OFFSETOF(chipcregs_t, gpioin); 2871 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); 2872} 2873 2874/* mask&set gpio interrupt polarity bits */ 2875uint32 2876si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) 2877{ 2878 si_info_t *sii; 2879 uint regoff; 2880 2881 sii = SI_INFO(sih); 2882 regoff = 0; 2883 2884 /* gpios could be shared on router platforms */ 2885 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 2886 mask = priority ? (si_gpioreservation & mask) : 2887 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 2888 val &= mask; 2889 } 2890 2891 regoff = OFFSETOF(chipcregs_t, gpiointpolarity); 2892 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 2893} 2894 2895/* mask&set gpio interrupt mask bits */ 2896uint32 2897si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) 2898{ 2899 si_info_t *sii; 2900 uint regoff; 2901 2902 sii = SI_INFO(sih); 2903 regoff = 0; 2904 2905 /* gpios could be shared on router platforms */ 2906 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { 2907 mask = priority ? (si_gpioreservation & mask) : 2908 ((si_gpioreservation | mask) & ~(si_gpioreservation)); 2909 val &= mask; 2910 } 2911 2912 regoff = OFFSETOF(chipcregs_t, gpiointmask); 2913 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); 2914} 2915 2916/* assign the gpio to an led */ 2917uint32 2918si_gpioled(si_t *sih, uint32 mask, uint32 val) 2919{ 2920 si_info_t *sii; 2921 2922 sii = SI_INFO(sih); 2923 if (sih->ccrev < 16) 2924 return 0xffffffff; 2925 2926 /* gpio led powersave reg */ 2927 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); 2928} 2929 2930/* mask&set gpio timer val */ 2931uint32 2932si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) 2933{ 2934 si_info_t *sii; 2935 2936 sii = SI_INFO(sih); 2937 2938 if (sih->ccrev < 16) 2939 return 0xffffffff; 2940 2941 return (si_corereg(sih, SI_CC_IDX, 2942 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); 2943} 2944 2945uint32 2946si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) 2947{ 2948 si_info_t *sii; 2949 uint offs; 2950 2951 sii = SI_INFO(sih); 2952 if (sih->ccrev < 20) 2953 return 0xffffffff; 2954 2955 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); 2956 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 2957} 2958 2959uint32 2960si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) 2961{ 2962 si_info_t *sii; 2963 uint offs; 2964 2965 sii = SI_INFO(sih); 2966 if (sih->ccrev < 11) 2967 return 0xffffffff; 2968 2969 if (regtype == GPIO_REGEVT) 2970 offs = OFFSETOF(chipcregs_t, gpioevent); 2971 else if (regtype == GPIO_REGEVT_INTMSK) 2972 offs = OFFSETOF(chipcregs_t, gpioeventintmask); 2973 else if (regtype == GPIO_REGEVT_INTPOL) 2974 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); 2975 else 2976 return 0xffffffff; 2977 2978 return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); 2979} 2980 2981void * 2982BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event, 2983 bool level, gpio_handler_t cb, void *arg) 2984{ 2985 si_info_t *sii; 2986 gpioh_item_t *gi; 2987 2988 ASSERT(event); 2989 ASSERT(cb != NULL); 2990 2991 sii = SI_INFO(sih); 2992 if (sih->ccrev < 11) 2993 return NULL; 2994 2995 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) 2996 return NULL; 2997 2998 bzero(gi, sizeof(gpioh_item_t)); 2999 gi->event = event; 3000 gi->handler = cb; 3001 gi->arg = arg; 3002 gi->level = level; 3003 3004 gi->next = sii->gpioh_head; 3005 sii->gpioh_head = gi; 3006 3007 return (void *)(gi); 3008} 3009 3010void 3011BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh) 3012{ 3013 si_info_t *sii; 3014 gpioh_item_t *p, *n; 3015 3016 sii = SI_INFO(sih); 3017 if (sih->ccrev < 11) 3018 return; 3019 3020 ASSERT(sii->gpioh_head != NULL); 3021 if ((void*)sii->gpioh_head == gpioh) { 3022 sii->gpioh_head = sii->gpioh_head->next; 3023 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 3024 return; 3025 } else { 3026 p = sii->gpioh_head; 3027 n = p->next; 3028 while (n) { 3029 if ((void*)n == gpioh) { 3030 p->next = n->next; 3031 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); 3032 return; 3033 } 3034 p = n; 3035 n = n->next; 3036 } 3037 } 3038 3039 ASSERT(0); /* Not found in list */ 3040} 3041 3042void 3043si_gpio_handler_process(si_t *sih) 3044{ 3045 si_info_t *sii; 3046 gpioh_item_t *h; 3047 uint32 status; 3048 uint32 level = si_gpioin(sih); 3049 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); 3050 3051 sii = SI_INFO(sih); 3052 for (h = sii->gpioh_head; h != NULL; h = h->next) { 3053 if (h->handler) { 3054 status = (h->level ? level : edge); 3055 3056 if (status & h->event) 3057 h->handler(status, h->arg); 3058 } 3059 } 3060 3061 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ 3062} 3063 3064uint32 3065si_gpio_int_enable(si_t *sih, bool enable) 3066{ 3067 si_info_t *sii; 3068 uint offs; 3069 3070 sii = SI_INFO(sih); 3071 if (sih->ccrev < 11) 3072 return 0xffffffff; 3073 3074 offs = OFFSETOF(chipcregs_t, intmask); 3075 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); 3076} 3077 3078 3079/* Return the size of the specified SOCRAM bank */ 3080static uint 3081socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type) 3082{ 3083 uint banksize, bankinfo; 3084 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 3085 3086 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM); 3087 3088 W_REG(sii->osh, ®s->bankidx, bankidx); 3089 bankinfo = R_REG(sii->osh, ®s->bankinfo); 3090 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1); 3091 return banksize; 3092} 3093 3094void 3095si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect) 3096{ 3097 si_info_t *sii; 3098 uint origidx; 3099 uint intr_val = 0; 3100 sbsocramregs_t *regs; 3101 bool wasup; 3102 uint corerev; 3103 3104 sii = SI_INFO(sih); 3105 3106 /* Block ints and save current core */ 3107 INTR_OFF(sii, intr_val); 3108 origidx = si_coreidx(sih); 3109 3110 if (!set) 3111 *enable = *protect = 0; 3112 3113 /* Switch to SOCRAM core */ 3114 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 3115 goto done; 3116 3117 /* Get info for determining size */ 3118 if (!(wasup = si_iscoreup(sih))) 3119 si_core_reset(sih, 0, 0); 3120 3121 corerev = si_corerev(sih); 3122 if (corerev >= 10) { 3123 uint32 extcinfo; 3124 uint8 nb; 3125 uint8 i; 3126 uint32 bankidx, bankinfo; 3127 3128 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 3129 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); 3130 for (i = 0; i < nb; i++) { 3131 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); 3132 W_REG(sii->osh, ®s->bankidx, bankidx); 3133 bankinfo = R_REG(sii->osh, ®s->bankinfo); 3134 if (set) { 3135 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK; 3136 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK; 3137 if (*enable) { 3138 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT); 3139 if (*protect) 3140 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT); 3141 } 3142 W_REG(sii->osh, ®s->bankinfo, bankinfo); 3143 } 3144 else if (i == 0) { 3145 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) { 3146 *enable = 1; 3147 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK) 3148 *protect = 1; 3149 } 3150 } 3151 } 3152 } 3153 3154 /* Return to previous state and core */ 3155 if (!wasup) 3156 si_core_disable(sih, 0); 3157 si_setcoreidx(sih, origidx); 3158 3159done: 3160 INTR_RESTORE(sii, intr_val); 3161} 3162 3163bool 3164si_socdevram_pkg(si_t *sih) 3165{ 3166 if (si_socdevram_size(sih) > 0) 3167 return TRUE; 3168 else 3169 return FALSE; 3170} 3171 3172uint32 3173si_socdevram_size(si_t *sih) 3174{ 3175 si_info_t *sii; 3176 uint origidx; 3177 uint intr_val = 0; 3178 uint32 memsize = 0; 3179 sbsocramregs_t *regs; 3180 bool wasup; 3181 uint corerev; 3182 3183 sii = SI_INFO(sih); 3184 3185 /* Block ints and save current core */ 3186 INTR_OFF(sii, intr_val); 3187 origidx = si_coreidx(sih); 3188 3189 /* Switch to SOCRAM core */ 3190 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 3191 goto done; 3192 3193 /* Get info for determining size */ 3194 if (!(wasup = si_iscoreup(sih))) 3195 si_core_reset(sih, 0, 0); 3196 3197 corerev = si_corerev(sih); 3198 if (corerev >= 10) { 3199 uint32 extcinfo; 3200 uint8 nb; 3201 uint8 i; 3202 3203 extcinfo = R_REG(sii->osh, ®s->extracoreinfo); 3204 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); 3205 for (i = 0; i < nb; i++) 3206 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); 3207 } 3208 3209 /* Return to previous state and core */ 3210 if (!wasup) 3211 si_core_disable(sih, 0); 3212 si_setcoreidx(sih, origidx); 3213 3214done: 3215 INTR_RESTORE(sii, intr_val); 3216 3217 return memsize; 3218} 3219 3220/* Return the RAM size of the SOCRAM core */ 3221uint32 3222si_socram_size(si_t *sih) 3223{ 3224 si_info_t *sii; 3225 uint origidx; 3226 uint intr_val = 0; 3227 3228 sbsocramregs_t *regs; 3229 bool wasup; 3230 uint corerev; 3231 uint32 coreinfo; 3232 uint memsize = 0; 3233 3234 sii = SI_INFO(sih); 3235 3236 /* Block ints and save current core */ 3237 INTR_OFF(sii, intr_val); 3238 origidx = si_coreidx(sih); 3239 3240 /* Switch to SOCRAM core */ 3241 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) 3242 goto done; 3243 3244 /* Get info for determining size */ 3245 if (!(wasup = si_iscoreup(sih))) 3246 si_core_reset(sih, 0, 0); 3247 corerev = si_corerev(sih); 3248 coreinfo = R_REG(sii->osh, ®s->coreinfo); 3249 3250 /* Calculate size from coreinfo based on rev */ 3251 if (corerev == 0) 3252 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); 3253 else if (corerev < 3) { 3254 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); 3255 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 3256 } else if ((corerev <= 7) || (corerev == 12)) { 3257 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 3258 uint bsz = (coreinfo & SRCI_SRBSZ_MASK); 3259 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; 3260 if (lss != 0) 3261 nb --; 3262 memsize = nb * (1 << (bsz + SR_BSZ_BASE)); 3263 if (lss != 0) 3264 memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); 3265 } else { 3266 uint8 i; 3267 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; 3268 for (i = 0; i < nb; i++) 3269 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); 3270 } 3271 3272 /* Return to previous state and core */ 3273 if (!wasup) 3274 si_core_disable(sih, 0); 3275 si_setcoreidx(sih, origidx); 3276 3277done: 3278 INTR_RESTORE(sii, intr_val); 3279 3280 return memsize; 3281} 3282 3283#ifdef BCMECICOEX 3284#define NOTIFY_BT_FM_DISABLE(sih, val) \ 3285 si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \ 3286 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE) 3287 3288/* Query OTP to see if FM is disabled */ 3289static int 3290BCMATTACHFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled) 3291{ 3292 int error = BCME_OK; 3293 uint bitoff = 0; 3294 bool wasup; 3295 void *oh; 3296 3297 /* Determine the bit for the chip */ 3298 switch (CHIPID(sih->chip)) { 3299 case BCM4325_CHIP_ID: 3300 if (CHIPREV(sih->chiprev) >= 6) 3301 bitoff = OTP4325_FM_DISABLED_OFFSET; 3302 break; 3303 default: 3304 break; 3305 } 3306 3307 /* If there is a bit for this chip, check it */ 3308 if (bitoff) { 3309 if (!(wasup = si_is_otp_powered(sih))) { 3310 si_otp_power(sih, TRUE); 3311 } 3312 3313 if ((oh = otp_init(sih)) != NULL) 3314 *FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET); 3315 else 3316 error = BCME_NOTFOUND; 3317 3318 if (!wasup) { 3319 si_otp_power(sih, FALSE); 3320 } 3321 } 3322 3323 return error; 3324} 3325 3326bool 3327si_eci(si_t *sih) 3328{ 3329 return (!!(sih->cccaps & CC_CAP_ECI)); 3330} 3331 3332bool 3333si_seci(si_t *sih) 3334{ 3335 return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT); 3336} 3337 3338/* ECI Init routine */ 3339int 3340BCMATTACHFN(si_eci_init)(si_t *sih) 3341{ 3342 uint32 origidx = 0; 3343 si_info_t *sii; 3344 chipcregs_t *cc; 3345 bool fast; 3346 uint16 FMDisabled = FALSE; 3347 3348 /* check for ECI capability */ 3349 if (!(sih->cccaps & CC_CAP_ECI)) 3350 return BCME_ERROR; 3351 3352 sii = SI_INFO(sih); 3353 fast = SI_FAST(sii); 3354 if (!fast) { 3355 origidx = sii->curidx; 3356 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 3357 return BCME_ERROR; 3358 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 3359 return BCME_ERROR; 3360 ASSERT(cc); 3361 3362 /* disable level based interrupts */ 3363 if (sih->ccrev < 35) { 3364 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0); 3365 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0); 3366 W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0); 3367 } 3368 else { 3369 W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0); 3370 W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0); 3371 } 3372 3373 /* Assign eci_output bits between 'wl' and dot11mac */ 3374 if (sih->ccrev < 35) { 3375 W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS); 3376 } 3377 else { 3378 W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS); 3379 W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS); 3380 } 3381 3382 /* enable only edge based interrupts 3383 * only toggle on bit 62 triggers an interrupt 3384 */ 3385 if (sih->ccrev < 35) { 3386 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0); 3387 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0); 3388 W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0); 3389 } 3390 else { 3391 W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0); 3392 W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0); 3393 } 3394 3395 /* restore previous core */ 3396 if (!fast) 3397 si_setcoreidx(sih, origidx); 3398 3399 /* if FM disabled in OTP, let BT know */ 3400 if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) { 3401 if (FMDisabled) { 3402 NOTIFY_BT_FM_DISABLE(sih, 1); 3403 } 3404 } 3405 3406 return 0; 3407} 3408 3409/* 3410 * Write values to BT on eci_output. 3411 */ 3412void 3413si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt) 3414{ 3415 uint32 offset; 3416 3417 /* Nothing to do if there is no eci */ 3418 if ((sih->cccaps & CC_CAP_ECI) == 0) 3419 return; 3420 3421 /* Clear interrupt bit by default */ 3422 if (interrupt) 3423 si_corereg(sih, SI_CC_IDX, (sih->ccrev < 35 ? 3424 OFFSETOF(chipcregs_t, eci.lt35.eci_output) : 3425 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)), 3426 (1 << 30), 0); 3427 3428 if (sih->ccrev >= 35) { 3429 if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) { 3430 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi); 3431 mask = mask & ~0xFFFF0000; 3432 } 3433 else { 3434 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo); 3435 mask = mask | (1<<30); 3436 val = val & ~(1 << 30); 3437 } 3438 } 3439 else { 3440 offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output); 3441 val = val & ~(1 << 30); 3442 } 3443 3444 si_corereg(sih, SI_CC_IDX, offset, mask, val); 3445 3446 /* Set interrupt bit if needed */ 3447 if (interrupt) 3448 si_corereg(sih, SI_CC_IDX, 3449 (sih->ccrev < 35 ? 3450 OFFSETOF(chipcregs_t, eci.lt35.eci_output) : 3451 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)), 3452 (1 << 30), (1 << 30)); 3453} 3454 3455/* seci clock enable/disable */ 3456static void 3457si_seci_clkreq(si_t *sih, bool enable) 3458{ 3459 uint32 clk_ctl_st; 3460 uint32 offset; 3461 uint32 val; 3462 3463 if (!si_seci(sih)) 3464 return; 3465 3466 if (enable) 3467 val = CLKCTL_STS_SECI_CLK_REQ; 3468 else 3469 val = 0; 3470 3471 offset = OFFSETOF(chipcregs_t, clk_ctl_st); 3472 3473 si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val); 3474 3475 if (!enable) 3476 return; 3477 3478 SPINWAIT((si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL), 100000); 3479 3480 clk_ctl_st = si_corereg(sih, 0, offset, 0, 0); 3481 if (enable) { 3482 if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) { 3483 SI_ERROR(("SECI clock is still not available\n")); 3484 return; 3485} 3486 } 3487} 3488 3489void 3490BCMINITFN(si_seci_down)(si_t *sih) 3491{ 3492 uint32 origidx = 0; 3493 si_info_t *sii; 3494 chipcregs_t *cc; 3495 bool fast; 3496 uint32 seci_conf; 3497 3498 if (!si_seci(sih)) 3499 return; 3500 3501 sii = SI_INFO(sih); 3502 fast = SI_FAST(sii); 3503 3504 if (!fast) { 3505 origidx = sii->curidx; 3506 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) 3507 return; 3508 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) 3509 return; 3510 ASSERT(cc); 3511 3512 /* put seci in reset */ 3513 seci_conf = R_REG(sii->osh, &cc->SECI_config); 3514 seci_conf &= ~SECI_ENAB_SECI_ECI; 3515 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3516 seci_conf |= SECI_RESET; 3517 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3518 3519 /* bring down the clock if up */ 3520 si_seci_clkreq(sih, FALSE); 3521 3522 /* restore previous core */ 3523 if (!fast) 3524 si_setcoreidx(sih, origidx); 3525} 3526 3527/* SECI Init routine, pass in seci_mode */ 3528void * 3529BCMINITFN(si_seci_init)(si_t *sih, uint8 seci_mode) 3530{ 3531 uint32 origidx = 0; 3532 uint32 offset; 3533 si_info_t *sii; 3534 void *ptr; 3535 chipcregs_t *cc; 3536 bool fast; 3537 uint32 seci_conf; 3538 uint32 regval; 3539 3540 if (sih->ccrev < 35) 3541 return NULL; 3542 3543 if (!si_seci(sih)) 3544 return NULL; 3545 3546 if (seci_mode > SECI_MODE_MASK) 3547 return NULL; 3548 3549 sii = SI_INFO(sih); 3550 fast = SI_FAST(sii); 3551 if (!fast) { 3552 origidx = sii->curidx; 3553 if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL) 3554 return NULL; 3555 } else if ((ptr = CCREGS_FAST(sii)) == NULL) 3556 return NULL; 3557 cc = (chipcregs_t *)ptr; 3558 ASSERT(cc); 3559 3560 3561 /* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */ 3562 if (CHIPID(sih->chip) == BCM43236_CHIP_ID || 3563 CHIPID(sih->chip) == BCM4331_CHIP_ID) { 3564 regval = R_REG(sii->osh, &cc->chipcontrol); 3565 regval |= 0x2; 3566 W_REG(sii->osh, &cc->chipcontrol, regval); 3567 3568 regval = R_REG(sii->osh, &cc->jtagctrl); 3569 regval |= 0x1; 3570 W_REG(sii->osh, &cc->jtagctrl, regval); 3571 } 3572 3573 /* enable SECI clock */ 3574 si_seci_clkreq(sih, TRUE); 3575 3576 /* put the SECI in reset */ 3577 seci_conf = R_REG(sii->osh, &cc->SECI_config); 3578 seci_conf &= ~SECI_ENAB_SECI_ECI; 3579 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3580 seci_conf = SECI_RESET; 3581 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3582 3583 /* set force-low, and set EN_SECI for all non-legacy modes */ 3584 seci_conf |= SECI_ENAB_SECIOUT_DIS; 3585 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) || 3586 (seci_mode == SECI_MODE_HALF_SECI)) 3587 { 3588 seci_conf |= SECI_ENAB_SECI_ECI; 3589 } 3590 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3591 3592 /* take seci out of reset */ 3593 seci_conf = R_REG(sii->osh, &cc->SECI_config); 3594 seci_conf &= ~(SECI_RESET); 3595 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3596 3597 /* set UART/SECI baud rate */ 3598 /* hard-coded at 4MBaud for now */ 3599 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) || 3600 (seci_mode == SECI_MODE_HALF_SECI)) { 3601 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv); 3602 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF); /* 4MBaud */ 3603 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj); 3604 if (CHIPID(sih->chip) == BCM43236_CHIP_ID || 3605 CHIPID(sih->chip) == BCM4331_CHIP_ID) { 3606 /* 43236 ccrev = 36 and MAC clk = 96MHz */ 3607 /* 4331 MAC clk = 96MHz */ 3608 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44); 3609 } 3610 else { 3611 /* 4336 MAC clk is 80MHz */ 3612 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22); 3613 } 3614 3615 /* LCR/MCR settings */ 3616 offset = OFFSETOF(chipcregs_t, seci_uart_lcr); 3617 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 3618 (SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */ 3619 offset = OFFSETOF(chipcregs_t, seci_uart_mcr); 3620 si_corereg(sih, SI_CC_IDX, offset, 3621 0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */ 3622 3623 /* Give control of ECI output regs to MAC core */ 3624 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo); 3625 si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS); 3626 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi); 3627 si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS); 3628 } 3629 3630 /* set the seci mode in seci conf register */ 3631 seci_conf = R_REG(sii->osh, &cc->SECI_config); 3632 seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT); 3633 seci_conf |= (seci_mode << SECI_MODE_SHIFT); 3634 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3635 3636 /* Clear force-low bit */ 3637 seci_conf = R_REG(sii->osh, &cc->SECI_config); 3638 seci_conf &= ~SECI_ENAB_SECIOUT_DIS; 3639 W_REG(sii->osh, &cc->SECI_config, seci_conf); 3640 3641 /* restore previous core */ 3642 if (!fast) 3643 si_setcoreidx(sih, origidx); 3644 3645 return ptr; 3646} 3647#endif /* BCMECICOEX */ 3648 3649void 3650si_btcgpiowar(si_t *sih) 3651{ 3652 si_info_t *sii; 3653 uint origidx; 3654 uint intr_val = 0; 3655 chipcregs_t *cc; 3656 3657 sii = SI_INFO(sih); 3658 3659 /* Make sure that there is ChipCommon core present && 3660 * UART_TX is strapped to 1 3661 */ 3662 if (!(sih->cccaps & CC_CAP_UARTGPIO)) 3663 return; 3664 3665 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ 3666 INTR_OFF(sii, intr_val); 3667 3668 origidx = si_coreidx(sih); 3669 3670 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3671 ASSERT(cc != NULL); 3672 3673 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); 3674 3675 /* restore the original index */ 3676 si_setcoreidx(sih, origidx); 3677 3678 INTR_RESTORE(sii, intr_val); 3679} 3680 3681#if !defined(_CFE_) || defined(CFG_WL) 3682void 3683si_chipcontrl_epa4331_restore(si_t *sih, uint32 val) 3684{ 3685 si_info_t *sii; 3686 chipcregs_t *cc; 3687 uint origidx; 3688 3689 sii = SI_INFO(sih); 3690 origidx = si_coreidx(sih); 3691 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3692 W_REG(sii->osh, &cc->chipcontrol, val); 3693 si_setcoreidx(sih, origidx); 3694} 3695 3696uint32 3697si_chipcontrl_epa4331_read(si_t *sih) 3698{ 3699 si_info_t *sii; 3700 chipcregs_t *cc; 3701 uint origidx; 3702 uint32 val; 3703 3704 sii = SI_INFO(sih); 3705 origidx = si_coreidx(sih); 3706 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3707 val = R_REG(sii->osh, &cc->chipcontrol); 3708 si_setcoreidx(sih, origidx); 3709 return val; 3710} 3711 3712void 3713si_chipcontrl_epa4331(si_t *sih, bool on) 3714{ 3715 si_info_t *sii; 3716 chipcregs_t *cc; 3717 uint origidx; 3718 uint32 val; 3719 3720 sii = SI_INFO(sih); 3721 origidx = si_coreidx(sih); 3722 3723 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3724 3725 val = R_REG(sii->osh, &cc->chipcontrol); 3726 3727 if (on) { 3728 if (sih->chippkg == 9 || sih->chippkg == 0xb) { 3729 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); 3730 /* Ext PA Controls for 4331 12x9 Package */ 3731 W_REG(sii->osh, &cc->chipcontrol, val); 3732 } else { 3733 /* Ext PA Controls for 4331 12x12 Package */ 3734 if (sih->chiprev > 0) { 3735 W_REG(sii->osh, &cc->chipcontrol, val | 3736 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2)); 3737 } else { 3738 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); 3739 } 3740 } 3741 } else { 3742 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5); 3743 W_REG(sii->osh, &cc->chipcontrol, val); 3744 } 3745 3746 si_setcoreidx(sih, origidx); 3747} 3748 3749void 3750si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) 3751{ 3752 si_info_t *sii; 3753 chipcregs_t *cc; 3754 uint origidx; 3755 uint32 val; 3756 bool sel_chip; 3757 3758 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) || 3759 (CHIPID(sih->chip) == BCM43431_CHIP_ID); 3760 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb)); 3761 3762 if (!sel_chip) 3763 return; 3764 3765 sii = SI_INFO(sih); 3766 origidx = si_coreidx(sih); 3767 3768 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3769 3770 val = R_REG(sii->osh, &cc->chipcontrol); 3771 3772 if (enter_wowl) { 3773 val |= CCTRL4331_EXTPA_EN; 3774 W_REG(sii->osh, &cc->chipcontrol, val); 3775 } else { 3776 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); 3777 W_REG(sii->osh, &cc->chipcontrol, val); 3778 } 3779 si_setcoreidx(sih, origidx); 3780} 3781#endif /* !_CFE_ || CFG_WL */ 3782 3783uint 3784si_pll_reset(si_t *sih) 3785{ 3786 uint err = 0; 3787 3788 uint intr_val = 0; 3789 si_info_t *sii; 3790 sii = SI_INFO(sih); 3791 INTR_OFF(sii, intr_val); 3792 err = si_pll_minresmask_reset(sih, sii->osh); 3793 INTR_RESTORE(sii, intr_val); 3794 return (err); 3795} 3796 3797/* Enable BT-COEX & Ex-PA for 4313 */ 3798void 3799si_epa_4313war(si_t *sih) 3800{ 3801 si_info_t *sii; 3802 chipcregs_t *cc; 3803 uint origidx; 3804 3805 sii = SI_INFO(sih); 3806 origidx = si_coreidx(sih); 3807 3808 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3809 3810 /* EPA Fix */ 3811 W_REG(sii->osh, &cc->gpiocontrol, 3812 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); 3813 3814 si_setcoreidx(sih, origidx); 3815} 3816 3817void 3818si_clk_pmu_htavail_set(si_t *sih, bool set_clear) 3819{ 3820 si_info_t *sii; 3821 sii = SI_INFO(sih); 3822 3823 si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear); 3824} 3825 3826/* WL/BT control for 4313 btcombo boards >= P250 */ 3827void 3828si_btcombo_p250_4313_war(si_t *sih) 3829{ 3830 si_info_t *sii; 3831 chipcregs_t *cc; 3832 uint origidx; 3833 3834 sii = SI_INFO(sih); 3835 origidx = si_coreidx(sih); 3836 3837 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3838 W_REG(sii->osh, &cc->gpiocontrol, 3839 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK); 3840 3841 W_REG(sii->osh, &cc->gpioouten, 3842 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK); 3843 3844 si_setcoreidx(sih, origidx); 3845} 3846void 3847si_btc_enable_chipcontrol(si_t *sih) 3848{ 3849 si_info_t *sii; 3850 chipcregs_t *cc; 3851 uint origidx; 3852 3853 sii = SI_INFO(sih); 3854 origidx = si_coreidx(sih); 3855 3856 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); 3857 3858 /* BT fix */ 3859 W_REG(sii->osh, &cc->chipcontrol, 3860 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK); 3861 3862 si_setcoreidx(sih, origidx); 3863} 3864/* check if the device is removed */ 3865bool 3866si_deviceremoved(si_t *sih) 3867{ 3868 uint32 w; 3869 si_info_t *sii; 3870 3871 sii = SI_INFO(sih); 3872 3873 switch (BUSTYPE(sih->bustype)) { 3874 case PCI_BUS: 3875 ASSERT(sii->osh != NULL); 3876 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); 3877 if ((w & 0xFFFF) != VENDOR_BROADCOM) 3878 return TRUE; 3879 break; 3880 } 3881 return FALSE; 3882} 3883 3884bool 3885si_is_sprom_available(si_t *sih) 3886{ 3887 if (sih->ccrev >= 31) { 3888 si_info_t *sii; 3889 uint origidx; 3890 chipcregs_t *cc; 3891 uint32 sromctrl; 3892 3893 if ((sih->cccaps & CC_CAP_SROM) == 0) 3894 return FALSE; 3895 3896 sii = SI_INFO(sih); 3897 origidx = sii->curidx; 3898 cc = si_setcoreidx(sih, SI_CC_IDX); 3899 sromctrl = R_REG(sii->osh, &cc->sromcontrol); 3900 si_setcoreidx(sih, origidx); 3901 return (sromctrl & SRC_PRESENT); 3902 } 3903 3904 switch (CHIPID(sih->chip)) { 3905 case BCM4312_CHIP_ID: 3906 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); 3907 case BCM4325_CHIP_ID: 3908 return (sih->chipst & CST4325_SPROM_SEL) != 0; 3909 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: 3910 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: 3911 case BCM43420_CHIP_ID: 3912 case BCM4342_CHIP_ID: { 3913 uint32 spromotp; 3914 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> 3915 CST4322_SPROM_OTP_SEL_SHIFT; 3916 return (spromotp & CST4322_SPROM_PRESENT) != 0; 3917 } 3918 case BCM4329_CHIP_ID: 3919 return (sih->chipst & CST4329_SPROM_SEL) != 0; 3920 case BCM4315_CHIP_ID: 3921 return (sih->chipst & CST4315_SPROM_SEL) != 0; 3922 case BCM4319_CHIP_ID: 3923 return (sih->chipst & CST4319_SPROM_SEL) != 0; 3924 case BCM4336_CHIP_ID: 3925 return (sih->chipst & CST4336_SPROM_PRESENT) != 0; 3926 case BCM4330_CHIP_ID: 3927 return (sih->chipst & CST4330_SPROM_PRESENT) != 0; 3928 case BCM4313_CHIP_ID: 3929 return (sih->chipst & CST4313_SPROM_PRESENT) != 0; 3930 case BCM4331_CHIP_ID: 3931 case BCM43431_CHIP_ID: 3932 return (sih->chipst & CST4331_SPROM_PRESENT) != 0; 3933 case BCM43228_CHIP_ID: 3934 case BCM43428_CHIP_ID: 3935 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; 3936 default: 3937 return TRUE; 3938 } 3939} 3940 3941bool 3942si_is_otp_disabled(si_t *sih) 3943{ 3944 switch (CHIPID(sih->chip)) { 3945 case BCM4325_CHIP_ID: 3946 return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN; 3947 case BCM4322_CHIP_ID: 3948 case BCM43221_CHIP_ID: 3949 case BCM43231_CHIP_ID: 3950 case BCM4342_CHIP_ID: 3951 return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> 3952 CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) != 3953 CST4322_OTP_PRESENT; 3954 case BCM4329_CHIP_ID: 3955 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN; 3956 case BCM4315_CHIP_ID: 3957 return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN; 3958 case BCM4319_CHIP_ID: 3959 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN; 3960 case BCM4336_CHIP_ID: 3961 return ((sih->chipst & CST4336_OTP_PRESENT) == 0); 3962 case BCM4330_CHIP_ID: 3963 return ((sih->chipst & CST4330_OTP_PRESENT) == 0); 3964 case BCM4313_CHIP_ID: 3965 return (sih->chipst & CST4313_OTP_PRESENT) == 0; 3966 /* These chips always have their OTP on */ 3967 case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: case BCM43222_CHIP_ID: 3968 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID: 3969 case BCM43421_CHIP_ID: 3970 case BCM43226_CHIP_ID: 3971 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID: 3972 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: 3973 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID: 3974 case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: 3975 default: 3976 return FALSE; 3977 } 3978} 3979 3980bool 3981si_is_otp_powered(si_t *sih) 3982{ 3983 if (PMUCTL_ENAB(sih)) 3984 return si_pmu_is_otp_powered(sih, si_osh(sih)); 3985 return TRUE; 3986} 3987 3988void 3989si_otp_power(si_t *sih, bool on) 3990{ 3991 if (PMUCTL_ENAB(sih)) 3992 si_pmu_otp_power(sih, si_osh(sih), on); 3993 OSL_DELAY(1000); 3994} 3995 3996bool 3997#if defined(WLTEST) 3998si_is_sprom_enabled(si_t *sih) 3999#else 4000BCMATTACHFN(si_is_sprom_enabled)(si_t *sih) 4001#endif 4002{ 4003 if (PMUCTL_ENAB(sih)) 4004 return si_pmu_is_sprom_enabled(sih, si_osh(sih)); 4005 return TRUE; 4006} 4007 4008void 4009#if defined(WLTEST) 4010si_sprom_enable(si_t *sih, bool enable) 4011#else 4012BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable) 4013#endif 4014{ 4015 if (PMUCTL_ENAB(sih)) 4016 si_pmu_sprom_enable(sih, si_osh(sih), enable); 4017} 4018 4019/* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */ 4020int 4021si_cis_source(si_t *sih) 4022{ 4023 /* Many chips have the same mapping of their chipstatus field */ 4024 static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM }; 4025 static const uint cis_sel_1b[] = { CIS_DEFAULT, CIS_OTP }; 4026 UNUSED_PARAMETER(cis_sel_1b); 4027 4028 /* PCI chips use SROM format instead of CIS */ 4029 if (BUSTYPE(sih->bustype) == PCI_BUS) 4030 return BCME_NOTFOUND; 4031 4032 switch (CHIPID(sih->chip)) { 4033 case BCM4325_CHIP_ID: 4034 return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ? 4035 CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)]; 4036 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: 4037 case BCM4342_CHIP_ID: { 4038 uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> 4039 CST4322_SPROM_OTP_SEL_SHIFT; 4040 return ((strap >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[strap]); 4041 } 4042 4043 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID: 4044 case BCM43234_CHIP_ID: { 4045 uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >> 4046 CST43236_OTP_SEL_SHIFT; 4047 UNUSED_PARAMETER(strap); 4048 return CIS_OTP; 4049 } 4050 4051 case BCM43237_CHIP_ID: { 4052 uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >> 4053 CST43237_OTP_SEL_SHIFT; 4054 return cis_sel_1b[strap]; 4055 } 4056 4057 case BCM4329_CHIP_ID: 4058 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ? 4059 CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)]; 4060 case BCM4315_CHIP_ID: 4061 return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ? 4062 CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)]; 4063 case BCM4319_CHIP_ID: { 4064 uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >> 4065 CST4319_SPROM_OTP_SEL_SHIFT); 4066 return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319]; 4067 } 4068 case BCM4336_CHIP_ID: { 4069 if (sih->chipst & CST4336_SPROM_PRESENT) 4070 return CIS_SROM; 4071 if (sih->chipst & CST4336_OTP_PRESENT) 4072 return CIS_OTP; 4073 return CIS_DEFAULT; 4074 } 4075 case BCM4330_CHIP_ID: { 4076 if (sih->chipst & CST4330_SPROM_PRESENT) 4077 return CIS_SROM; 4078 if (sih->chipst & CST4330_OTP_PRESENT) 4079 return CIS_OTP; 4080 return CIS_DEFAULT; 4081 } 4082 default: 4083 return CIS_DEFAULT; 4084 } 4085} 4086 4087/* Read/write to OTP to find the FAB manf */ 4088int 4089BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw) 4090{ 4091 int error = BCME_OK; 4092 uint offset = 0; 4093 uint16 data, mask = 0, shift = 0; 4094 4095 switch (CHIPID(sih->chip)) { 4096 case BCM4329_CHIP_ID: 4097 /* Bit locations 133-130 */ 4098 if (sih->chiprev >= 3) { 4099 offset = 8; 4100 mask = 0x3c; 4101 shift = 2; 4102 } 4103 break; 4104 case BCM5356_CHIP_ID: 4105 /* Bit locations 133-130 */ 4106 offset = 8; 4107 mask = 0x3c; 4108 shift = 2; 4109 break; 4110 default: 4111 error = BCME_EPERM; 4112 return error; 4113 } 4114 4115 if (rw == TRUE) { 4116 /* TRUE --> read */ 4117 error = otp_read_word(sih, offset, &data); 4118 if (!error) 4119 *fabid = (data & mask) >> shift; 4120 } else { 4121 data = *fabid; 4122 data = (data << shift) & mask; 4123#ifdef BCMNVRAMW 4124 error = otp_write_word(sih, offset, data); 4125#endif /* BCMNVRAMW */ 4126 } 4127 4128 return error; 4129} 4130 4131uint16 BCMINITFN(si_fabid)(si_t *sih) 4132{ 4133 uint16 fabid = 0; 4134 if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK) 4135 { 4136 SI_ERROR(("si_fabid: reading fabid from otp failed.\n")); 4137 } 4138 4139 return fabid; 4140} 4141