2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 #include <pcie_core.h>
38 #include <sbsdpcmdev.h>
43 /* this file now contains only definitions for sb functions, only necessary
44 *for devices using Sonics backplanes (bcm4329)
47 /* if an amba SDIO device is supported, please further restrict the inclusion
51 #include "siutils_priv.h"
54 /* local prototypes */
55 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
56 void *regs, uint bustype, void *sdh, char **vars,
58 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
60 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
61 uint32 savewin, uint *origidx, void *regs);
62 static void si_nvram_process(si_info_t *sii, char *pvars);
64 /* dev path concatenation util */
65 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
66 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
67 static bool si_ispcie(si_info_t *sii);
68 static uint BCMINITFN(socram_banksize) (si_info_t *sii, sbsocramregs_t *r,
69 uint8 idx, uint8 mtype);
71 /* global variable to indicate reservation/release of gpio's */
72 static uint32 si_gpioreservation = 0;
74 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
77 * Allocate a si handle.
78 * devid - pci device id (used to determine chip#)
79 * osh - opaque OS handle
80 * regs - virtual address of initial core registers
81 * bustype - pci/sb/sdio/etc
82 * vars - pointer to a pointer area for "environment" variables
83 * varsz - pointer to int to return the size of the vars
85 si_t *BCMATTACHFN(si_attach) (uint devid, osl_t *osh, void *regs,
86 uint bustype, void *sdh, char **vars,
91 if ((sii = MALLOC(osh, sizeof(si_info_t))) == NULL) {
92 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n",
97 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
99 MFREE(osh, sii, sizeof(si_info_t));
102 sii->vars = vars ? *vars : NULL;
103 sii->varsz = varsz ? *varsz : 0;
108 /* global kernel resource */
109 static si_info_t ksii;
111 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
114 BCMATTACHFN(si_buscore_prep) (si_info_t *sii, uint bustype, uint devid,
117 /* kludge to enable the clock on the 4306 which lacks a slowclock */
118 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
119 si_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
122 if (BUSTYPE(bustype) == SDIO_BUS) {
126 /* Try forcing SDIO core to do ALPAvail request only */
127 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
128 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
133 /* If register supported, wait for ALPAvail and then force ALP */
135 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
136 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
137 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
139 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
140 SBSDIO_FUNC1_CHIPCLKCSR,
142 !SBSDIO_ALPAV(clkval)),
143 PMU_MAX_TRANSITION_DLY);
144 if (!SBSDIO_ALPAV(clkval)) {
145 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval));
149 SBSDIO_FORCE_HW_CLKREQ_OFF |
151 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
152 SBSDIO_FUNC1_CHIPCLKCSR,
158 /* Also, disable the extra SDIO pull-ups */
159 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
162 #endif /* defined(BCMSDIO) */
168 BCMATTACHFN(si_buscore_setup) (si_info_t *sii, chipcregs_t *cc, uint bustype,
169 uint32 savewin, uint *origidx, void *regs) {
172 uint pciidx, pcieidx, pcirev, pcierev;
174 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
175 ASSERT((uintptr) cc);
177 /* get chipcommon rev */
178 sii->pub.ccrev = (int)si_corerev(&sii->pub);
180 /* get chipcommon chipstatus */
181 if (sii->pub.ccrev >= 11)
182 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
184 /* get chipcommon capabilites */
185 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
186 /* get chipcommon extended capabilities */
188 if (sii->pub.ccrev >= 35)
189 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
191 /* get pmu rev and caps */
192 if (sii->pub.cccaps & CC_CAP_PMU) {
193 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
194 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
198 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
199 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
203 /* figure out bus/orignal core idx */
204 sii->pub.buscoretype = NODEV_CORE_ID;
205 sii->pub.buscorerev = NOREV;
206 sii->pub.buscoreidx = BADIDX;
209 pcirev = pcierev = NOREV;
210 pciidx = pcieidx = BADIDX;
212 for (i = 0; i < sii->numcores; i++) {
215 si_setcoreidx(&sii->pub, i);
216 cid = si_coreid(&sii->pub);
217 crev = si_corerev(&sii->pub);
219 /* Display cores found */
220 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
221 i, cid, crev, sii->coresba[i], sii->regs[i]));
223 if (BUSTYPE(bustype) == PCI_BUS) {
224 if (cid == PCI_CORE_ID) {
228 } else if (cid == PCIE_CORE_ID) {
235 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
236 (BUSTYPE(bustype) == SPI_BUS)) &&
237 ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) {
238 sii->pub.buscorerev = crev;
239 sii->pub.buscoretype = cid;
240 sii->pub.buscoreidx = i;
244 /* find the core idx before entering this func. */
245 if ((savewin && (savewin == sii->coresba[i])) ||
246 (regs == sii->regs[i]))
257 sii->pub.buscoretype = PCI_CORE_ID;
258 sii->pub.buscorerev = pcirev;
259 sii->pub.buscoreidx = pciidx;
261 sii->pub.buscoretype = PCIE_CORE_ID;
262 sii->pub.buscorerev = pcierev;
263 sii->pub.buscoreidx = pcieidx;
266 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
267 sii->pub.buscoretype, sii->pub.buscorerev));
269 /* fixup necessary chip/core configurations */
270 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
274 (void *)(uintptr) pcicore_init(&sii->pub,
281 if (si_pci_fixcfg(&sii->pub)) {
282 SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
287 /* return to the original core */
288 si_setcoreidx(&sii->pub, *origidx);
293 static void BCMATTACHFN(si_nvram_process) (si_info_t *sii, char *pvars) {
296 /* get boardtype and boardrev */
297 switch (BUSTYPE(sii->pub.bustype)) {
299 /* do a pci config read to get subsystem id and subvendor id */
300 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
301 /* Let nvram variables override subsystem Vend/ID */
302 if ((sii->pub.boardvendor =
303 (uint16) si_getdevpathintvar(&sii->pub, "boardvendor"))
305 sii->pub.boardvendor = w & 0xffff;
307 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii->pub.boardvendor, w & 0xffff));
308 if ((sii->pub.boardtype =
309 (uint16) si_getdevpathintvar(&sii->pub, "boardtype"))
311 sii->pub.boardtype = (w >> 16) & 0xffff;
313 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii->pub.boardtype, (w >> 16) & 0xffff));
319 sii->pub.boardvendor = getintvar(pvars, "manfid");
320 sii->pub.boardtype = getintvar(pvars, "prodid");
325 sii->pub.boardvendor = VENDOR_BROADCOM;
326 sii->pub.boardtype = SPI_BOARD;
332 sii->pub.boardvendor = VENDOR_BROADCOM;
334 || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
335 if ((sii->pub.boardtype =
336 getintvar(NULL, "boardtype")) == 0)
337 sii->pub.boardtype = 0xffff;
341 if (sii->pub.boardtype == 0) {
342 SI_ERROR(("si_doattach: unknown board type\n"));
343 ASSERT(sii->pub.boardtype);
346 sii->pub.boardflags = getintvar(pvars, "boardflags");
349 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
350 /* this has been customized for the bcm 4329 ONLY */
352 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
353 osl_t *osh, void *regs,
354 uint bustype, void *sdh,
355 char **vars, uint *varsz) {
356 struct si_pub *sih = &sii->pub;
362 ASSERT(GOODREGS(regs));
364 bzero((uchar *) sii, sizeof(si_info_t));
368 sih->buscoreidx = BADIDX;
374 /* find Chipcommon address */
375 cc = (chipcregs_t *) sii->curmap;
376 sih->bustype = bustype;
378 if (bustype != BUSTYPE(bustype)) {
379 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
383 /* bus/core/clk setup for register access */
384 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
385 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
390 /* ChipID recognition.
391 * We assume we can read chipid at offset 0 from the regs arg.
392 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
393 * some way of recognizing them needs to be added here.
395 w = R_REG(osh, &cc->chipid);
396 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
397 /* Might as wll fill in chip id rev & pkg */
398 sih->chip = w & CID_ID_MASK;
399 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
400 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
402 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
403 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
404 sih->chippkg = BCM4329_182PIN_PKG_ID;
406 sih->issim = IS_SIM(sih->chippkg);
409 /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
410 sb_scan(&sii->pub, regs, devid);
412 /* no cores found, bail out */
413 if (sii->numcores == 0) {
414 SI_ERROR(("si_doattach: could not find any cores\n"));
417 /* bus/core/clk setup */
419 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
420 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
424 /* Init nvram from flash if it exists */
425 nvram_init((void *)&(sii->pub));
427 /* Init nvram from sprom/otp if they exist */
429 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
430 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
433 pvars = vars ? *vars : NULL;
434 si_nvram_process(sii, pvars);
436 /* === NVRAM, clock is ready === */
438 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
439 W_REG(osh, &cc->gpiopullup, 0);
440 W_REG(osh, &cc->gpiopulldown, 0);
441 sb_setcoreidx(sih, origidx);
443 /* PMU specific initializations */
444 if (PMUCTL_ENAB(sih)) {
446 si_pmu_init(sih, sii->osh);
447 si_pmu_chip_init(sih, sii->osh);
448 xtalfreq = getintvar(pvars, "xtalfreq");
449 /* If xtalfreq var not available, try to measure it */
451 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
452 si_pmu_pll_init(sih, sii->osh, xtalfreq);
453 si_pmu_res_init(sih, sii->osh);
454 si_pmu_swreg_init(sih, sii->osh);
457 /* setup the GPIO based LED powersave register */
458 if ((w = getintvar(pvars, "leddc")) == 0)
459 w = DEFAULT_GPIOTIMERVAL;
460 sb_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
463 /* clear any previous epidiag-induced target abort */
464 sb_taclear(sih, FALSE);
474 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
475 osl_t *osh, void *regs,
476 uint bustype, void *sdh,
477 char **vars, uint *varsz) {
478 struct si_pub *sih = &sii->pub;
484 ASSERT(GOODREGS(regs));
486 bzero((uchar *) sii, sizeof(si_info_t));
490 sih->buscoreidx = BADIDX;
496 /* check to see if we are a si core mimic'ing a pci core */
497 if ((bustype == PCI_BUS) &&
498 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) ==
500 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " "devid:0x%x\n", __func__, devid));
504 /* find Chipcommon address */
505 if (bustype == PCI_BUS) {
507 OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
508 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
509 savewin = SI_ENUM_BASE;
510 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
511 cc = (chipcregs_t *) regs;
513 cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
516 sih->bustype = bustype;
517 if (bustype != BUSTYPE(bustype)) {
518 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
522 /* bus/core/clk setup for register access */
523 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
524 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
529 /* ChipID recognition.
530 * We assume we can read chipid at offset 0 from the regs arg.
531 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
532 * some way of recognizing them needs to be added here.
534 w = R_REG(osh, &cc->chipid);
535 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
536 /* Might as wll fill in chip id rev & pkg */
537 sih->chip = w & CID_ID_MASK;
538 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
539 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
541 sih->issim = IS_SIM(sih->chippkg);
544 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
545 SI_MSG(("Found chip type AI (0x%08x)\n", w));
546 /* pass chipc address instead of original core base */
547 ai_scan(&sii->pub, (void *)(uintptr) cc, devid);
549 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
552 /* no cores found, bail out */
553 if (sii->numcores == 0) {
554 SI_ERROR(("si_doattach: could not find any cores\n"));
557 /* bus/core/clk setup */
559 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
560 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
564 /* assume current core is CC */
565 if ((sii->pub.ccrev == 0x25)
567 ((CHIPID(sih->chip) == BCM43236_CHIP_ID
568 || CHIPID(sih->chip) == BCM43235_CHIP_ID
569 || CHIPID(sih->chip) == BCM43238_CHIP_ID)
570 && (CHIPREV(sii->pub.chiprev) <= 2))) {
572 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
574 clkdiv = R_REG(osh, &cc->clkdiv);
575 /* otp_clk_div is even number, 120/14 < 9mhz */
576 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
577 W_REG(osh, &cc->clkdiv, clkdiv);
578 SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
583 /* Init nvram from flash if it exists */
584 nvram_init((void *)&(sii->pub));
586 /* Init nvram from sprom/otp if they exist */
588 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
589 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
592 pvars = vars ? *vars : NULL;
593 si_nvram_process(sii, pvars);
595 /* === NVRAM, clock is ready === */
596 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
597 W_REG(osh, &cc->gpiopullup, 0);
598 W_REG(osh, &cc->gpiopulldown, 0);
599 si_setcoreidx(sih, origidx);
601 /* PMU specific initializations */
602 if (PMUCTL_ENAB(sih)) {
604 si_pmu_init(sih, sii->osh);
605 si_pmu_chip_init(sih, sii->osh);
606 xtalfreq = getintvar(pvars, "xtalfreq");
607 /* If xtalfreq var not available, try to measure it */
609 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
610 si_pmu_pll_init(sih, sii->osh, xtalfreq);
611 si_pmu_res_init(sih, sii->osh);
612 si_pmu_swreg_init(sih, sii->osh);
615 /* setup the GPIO based LED powersave register */
616 if ((w = getintvar(pvars, "leddc")) == 0)
617 w = DEFAULT_GPIOTIMERVAL;
618 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
621 ASSERT(sii->pch != NULL);
622 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
625 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
626 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
627 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
628 if (CHIPREV(sih->chiprev) == 0) {
629 SI_MSG(("Applying 43224A0 WARs\n"));
630 si_corereg(sih, SI_CC_IDX,
631 OFFSETOF(chipcregs_t, chipcontrol),
632 CCTRL43224_GPIO_TOGGLE,
633 CCTRL43224_GPIO_TOGGLE);
634 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
635 CCTRL_43224A0_12MA_LED_DRIVE);
637 if (CHIPREV(sih->chiprev) >= 1) {
638 SI_MSG(("Applying 43224B0+ WARs\n"));
639 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
640 CCTRL_43224B0_12MA_LED_DRIVE);
644 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
645 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
646 SI_MSG(("Applying 4313 WARs\n"));
647 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
648 CCTRL_4313_12MA_LED_DRIVE);
651 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
652 /* Enable Ext PA lines depending on chip package option */
653 si_chipcontrl_epa4331(sih, TRUE);
658 if (BUSTYPE(sih->bustype) == PCI_BUS) {
660 pcicore_deinit(sii->pch);
668 /* may be called with core in reset */
669 void BCMATTACHFN(si_detach) (si_t *sih) {
673 struct si_pub *si_local = NULL;
674 bcopy(&sih, &si_local, sizeof(si_t **));
681 if (BUSTYPE(sih->bustype) == SI_BUS)
682 for (idx = 0; idx < SI_MAXCORES; idx++)
683 if (sii->regs[idx]) {
684 REG_UNMAP(sii->regs[idx]);
685 sii->regs[idx] = NULL;
688 nvram_exit((void *)si_local); /* free up nvram buffers */
690 if (BUSTYPE(sih->bustype) == PCI_BUS) {
692 pcicore_deinit(sii->pch);
695 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
697 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
698 MFREE(sii->osh, sii, sizeof(si_info_t));
701 void *si_osh(si_t *sih)
709 void si_setosh(si_t *sih, osl_t *osh)
714 if (sii->osh != NULL) {
715 SI_ERROR(("osh is already set....\n"));
721 /* register driver interrupt disabling and restoring callback functions */
723 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
724 void *intrsenabled_fn, void *intr_arg)
729 sii->intr_arg = intr_arg;
730 sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
731 sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
732 sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
733 /* save current core id. when this function called, the current core
734 * must be the core which provides driver functions(il, et, wl, etc.)
736 sii->dev_coreid = sii->coreid[sii->curidx];
739 void si_deregister_intr_callback(si_t *sih)
744 sii->intrsoff_fn = NULL;
747 uint si_intflag(si_t *sih)
749 si_info_t *sii = SI_INFO(sih);
751 if (CHIPTYPE(sih->socitype) == SOCI_AI)
752 return R_REG(sii->osh,
753 ((uint32 *) (uintptr) (sii->oob_router +
761 uint si_flag(si_t *sih)
763 if (CHIPTYPE(sih->socitype) == SOCI_AI)
771 void si_setint(si_t *sih, int siflag)
773 if (CHIPTYPE(sih->socitype) == SOCI_AI)
774 ai_setint(sih, siflag);
780 uint si_coreid(si_t *sih)
785 return sii->coreid[sii->curidx];
789 uint si_coreidx(si_t *sih)
797 /* return the core-type instantiation # of the current core */
798 uint si_coreunit(si_t *sih)
811 ASSERT(GOODREGS(sii->curmap));
812 coreid = si_coreid(sih);
814 /* count the cores of our type */
815 for (i = 0; i < idx; i++)
816 if (sii->coreid[i] == coreid)
822 uint si_corevendor(si_t *sih)
824 if (CHIPTYPE(sih->socitype) == SOCI_AI)
825 return ai_corevendor(sih);
832 bool si_backplane64(si_t *sih)
834 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
838 uint si_corerev(si_t *sih)
840 if (CHIPTYPE(sih->socitype) == SOCI_AI)
841 return ai_corerev(sih);
849 /* return index of coreid or BADIDX if not found */
850 uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
860 for (i = 0; i < sii->numcores; i++)
861 if (sii->coreid[i] == coreid) {
862 if (found == coreunit)
870 /* return list of found cores */
871 uint si_corelist(si_t *sih, uint coreid[])
877 bcopy((uchar *) sii->coreid, (uchar *) coreid,
878 (sii->numcores * sizeof(uint)));
879 return (sii->numcores);
882 /* return current register mapping */
883 void *si_coreregs(si_t *sih)
888 ASSERT(GOODREGS(sii->curmap));
890 return (sii->curmap);
894 * This function changes logical "focus" to the indicated core;
895 * must be called with interrupts off.
896 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
898 void *si_setcore(si_t *sih, uint coreid, uint coreunit)
902 idx = si_findcoreidx(sih, coreid, coreunit);
906 if (CHIPTYPE(sih->socitype) == SOCI_AI)
907 return ai_setcoreidx(sih, idx);
910 return sb_setcoreidx(sih, idx);
919 void *si_setcoreidx(si_t *sih, uint coreidx)
921 if (CHIPTYPE(sih->socitype) == SOCI_AI)
922 return ai_setcoreidx(sih, coreidx);
930 /* Turn off interrupt as required by sb_setcore, before switch core */
931 void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
939 /* Overloading the origidx variable to remember the coreid,
940 * this works because the core ids cannot be confused with
944 if (coreid == CC_CORE_ID)
945 return (void *)CCREGS_FAST(sii);
946 else if (coreid == sih->buscoretype)
947 return (void *)PCIEREGS(sii);
949 INTR_OFF(sii, *intr_val);
950 *origidx = sii->curidx;
951 cc = si_setcore(sih, coreid, 0);
957 /* restore coreidx and restore interrupt */
958 void si_restore_core(si_t *sih, uint coreid, uint intr_val)
964 && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
967 si_setcoreidx(sih, coreid);
968 INTR_RESTORE(sii, intr_val);
971 int si_numaddrspaces(si_t *sih)
973 if (CHIPTYPE(sih->socitype) == SOCI_AI)
974 return ai_numaddrspaces(sih);
981 uint32 si_addrspace(si_t *sih, uint asidx)
983 if (CHIPTYPE(sih->socitype) == SOCI_AI)
984 return ai_addrspace(sih, asidx);
991 uint32 si_addrspacesize(si_t *sih, uint asidx)
993 if (CHIPTYPE(sih->socitype) == SOCI_AI)
994 return ai_addrspacesize(sih, asidx);
1001 uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1003 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1004 return ai_core_cflags(sih, mask, val);
1011 void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1013 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1014 ai_core_cflags_wo(sih, mask, val);
1019 uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1021 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1022 return ai_core_sflags(sih, mask, val);
1029 bool si_iscoreup(si_t *sih)
1031 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1032 return ai_iscoreup(sih);
1035 return sb_iscoreup(sih);
1043 void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1045 /* only for 4319, no requirement for SOCI_SB */
1046 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1047 ai_write_wrap_reg(sih, offset, val);
1051 uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1054 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1055 return ai_corereg(sih, coreidx, regoff, mask, val);
1058 return sb_corereg(sih, coreidx, regoff, mask, val);
1066 void si_core_disable(si_t *sih, uint32 bits)
1069 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1070 ai_core_disable(sih, bits);
1073 sb_core_disable(sih, bits);
1077 void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1079 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1080 ai_core_reset(sih, bits, resetbits);
1083 sb_core_reset(sih, bits, resetbits);
1087 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1088 int si_corebist(si_t *sih)
1093 /* Read core control flags */
1094 cflags = si_core_cflags(sih, 0, 0);
1096 /* Set bist & fgc */
1097 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1099 /* Wait for bist done */
1100 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1102 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1103 result = BCME_ERROR;
1105 /* Reset core control flags */
1106 si_core_cflags(sih, 0xffff, cflags);
1111 static uint32 BCMINITFN(factor6) (uint32 x) {
1130 /* calculate the speed the SI would run at given a set of clockcontrol values */
1131 uint32 BCMINITFN(si_clock_rate) (uint32 pll_type, uint32 n, uint32 m) {
1132 uint32 n1, n2, clock, m1, m2, m3, mc;
1134 n1 = n & CN_N1_MASK;
1135 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1137 if (pll_type == PLL_TYPE6) {
1138 if (m & CC_T6_MMASK)
1142 } else if ((pll_type == PLL_TYPE1) ||
1143 (pll_type == PLL_TYPE3) ||
1144 (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1147 } else if (pll_type == PLL_TYPE2) {
1150 ASSERT((n1 >= 2) && (n1 <= 7));
1151 ASSERT((n2 >= 5) && (n2 <= 23));
1152 } else if (pll_type == PLL_TYPE5) {
1156 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1157 if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) {
1158 clock = CC_CLOCK_BASE2 * n1 * n2;
1160 clock = CC_CLOCK_BASE1 * n1 * n2;
1165 m1 = m & CC_M1_MASK;
1166 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1167 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1168 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1170 if ((pll_type == PLL_TYPE1) ||
1171 (pll_type == PLL_TYPE3) ||
1172 (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1174 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1184 return (clock / m1);
1186 return (clock / (m1 * m2));
1188 return (clock / (m1 * m2 * m3));
1190 return (clock / (m1 * m3));
1195 ASSERT(pll_type == PLL_TYPE2);
1200 ASSERT((m1 >= 2) && (m1 <= 7));
1201 ASSERT((m2 >= 3) && (m2 <= 10));
1202 ASSERT((m3 >= 2) && (m3 <= 7));
1204 if ((mc & CC_T2MC_M1BYP) == 0)
1206 if ((mc & CC_T2MC_M2BYP) == 0)
1208 if ((mc & CC_T2MC_M3BYP) == 0)
1215 uint32 BCMINITFN(si_clock) (si_t *sih) {
1220 uint32 pll_type, rate;
1224 INTR_OFF(sii, intr_val);
1225 if (PMUCTL_ENAB(sih)) {
1226 rate = si_pmu_si_clock(sih, sii->osh);
1231 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1234 n = R_REG(sii->osh, &cc->clockcontrol_n);
1235 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1236 if (pll_type == PLL_TYPE6)
1237 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1238 else if (pll_type == PLL_TYPE3)
1239 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1241 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1243 /* calculate rate */
1244 rate = si_clock_rate(pll_type, n, m);
1246 if (pll_type == PLL_TYPE3)
1249 /* switch back to previous core */
1250 si_setcoreidx(sih, idx);
1252 INTR_RESTORE(sii, intr_val);
1257 uint32 BCMINITFN(si_alp_clock) (si_t *sih) {
1258 if (PMUCTL_ENAB(sih))
1259 return si_pmu_alp_clock(sih, si_osh(sih));
1264 uint32 BCMINITFN(si_ilp_clock) (si_t *sih) {
1265 if (PMUCTL_ENAB(sih))
1266 return si_pmu_ilp_clock(sih, si_osh(sih));
1271 /* set chip watchdog reset timer to fire in 'ticks' */
1272 void si_watchdog(si_t *sih, uint ticks)
1276 if (PMUCTL_ENAB(sih)) {
1278 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1279 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1280 si_corereg(sih, SI_CC_IDX,
1281 OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1282 si_setcore(sih, USB20D_CORE_ID, 0);
1283 si_core_disable(sih, 1);
1284 si_setcore(sih, CC_CORE_ID, 0);
1287 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1288 /* The mips compiler uses the sllv instruction,
1289 * so we specially handle the 32-bit case.
1294 maxt = ((1 << nb) - 1);
1298 else if (ticks > maxt)
1301 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog),
1304 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1305 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1306 maxt = (1 << 28) - 1;
1310 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
1315 /* trigger watchdog reset after ms milliseconds */
1316 void si_watchdog_ms(si_t *sih, uint32 ms)
1318 si_watchdog(sih, wd_msticks * ms);
1321 uint16 BCMATTACHFN(si_d11_devid) (si_t *sih) {
1322 si_info_t *sii = SI_INFO(sih);
1325 /* normal case: nvram variable with devpath->devid->wl0id */
1326 if ((device = (uint16) si_getdevpathintvar(sih, "devid")) != 0) ;
1327 /* Get devid from OTP/SPROM depending on where the SROM is read */
1328 else if ((device = (uint16) getintvar(sii->vars, "devid")) != 0) ;
1329 /* no longer support wl0id, but keep the code here for backward compatibility. */
1330 else if ((device = (uint16) getintvar(sii->vars, "wl0id")) != 0) ;
1338 /* return the slow clock source - LPO, XTAL, or PCI */
1339 static uint si_slowclk_src(si_info_t *sii)
1343 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1345 if (sii->pub.ccrev < 6) {
1346 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1347 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32))
1348 & PCI_CFG_GPIO_SCS))
1349 return (SCC_SS_PCI);
1351 return (SCC_SS_XTAL);
1352 } else if (sii->pub.ccrev < 10) {
1353 cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
1354 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1355 } else /* Insta-clock */
1356 return (SCC_SS_XTAL);
1359 /* return the ILP (slowclock) min or max frequency */
1360 static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1365 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1367 /* shouldn't be here unless we've established the chip has dynamic clk control */
1368 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1370 slowclk = si_slowclk_src(sii);
1371 if (sii->pub.ccrev < 6) {
1372 if (slowclk == SCC_SS_PCI)
1373 return (max_freq ? (PCIMAXFREQ / 64)
1374 : (PCIMINFREQ / 64));
1376 return (max_freq ? (XTALMAXFREQ / 32)
1377 : (XTALMINFREQ / 32));
1378 } else if (sii->pub.ccrev < 10) {
1380 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
1382 if (slowclk == SCC_SS_LPO)
1383 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1384 else if (slowclk == SCC_SS_XTAL)
1385 return (max_freq ? (XTALMAXFREQ / div)
1386 : (XTALMINFREQ / div));
1387 else if (slowclk == SCC_SS_PCI)
1388 return (max_freq ? (PCIMAXFREQ / div)
1389 : (PCIMINFREQ / div));
1393 /* Chipc rev 10 is InstaClock */
1394 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1395 div = 4 * (div + 1);
1396 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1401 static void BCMINITFN(si_clkctl_setdelay) (si_info_t *sii, void *chipcregs) {
1402 chipcregs_t *cc = (chipcregs_t *) chipcregs;
1403 uint slowmaxfreq, pll_delay, slowclk;
1404 uint pll_on_delay, fref_sel_delay;
1406 pll_delay = PLL_DELAY;
1408 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1409 * since the xtal will also be powered down by dynamic clk control logic.
1412 slowclk = si_slowclk_src(sii);
1413 if (slowclk != SCC_SS_XTAL)
1414 pll_delay += XTAL_ON_DELAY;
1416 /* Starting with 4318 it is ILP that is used for the delays */
1418 si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1420 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1421 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1423 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1424 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1427 /* initialize power control delay registers */
1428 void BCMINITFN(si_clkctl_init) (si_t *sih) {
1434 if (!CCCTL_ENAB(sih))
1438 fast = SI_FAST(sii);
1440 origidx = sii->curidx;
1442 (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1444 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1448 /* set all Instaclk chip ILP to 1 MHz */
1449 if (sih->ccrev >= 10)
1450 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1451 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1453 si_clkctl_setdelay(sii, (void *)(uintptr) cc);
1456 si_setcoreidx(sih, origidx);
1459 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1460 uint16 BCMINITFN(si_clkctl_fast_pwrup_delay) (si_t *sih) {
1470 if (PMUCTL_ENAB(sih)) {
1471 INTR_OFF(sii, intr_val);
1472 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1473 INTR_RESTORE(sii, intr_val);
1477 if (!CCCTL_ENAB(sih))
1480 fast = SI_FAST(sii);
1483 origidx = sii->curidx;
1484 INTR_OFF(sii, intr_val);
1486 (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1488 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1492 slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1493 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1494 (slowminfreq - 1)) / slowminfreq;
1498 si_setcoreidx(sih, origidx);
1499 INTR_RESTORE(sii, intr_val);
1504 /* turn primary xtal and/or pll off/on */
1505 int si_clkctl_xtal(si_t *sih, uint what, bool on)
1508 uint32 in, out, outen;
1512 switch (BUSTYPE(sih->bustype)) {
1517 #endif /* BCMSDIO */
1520 /* pcie core doesn't have any mapping to control the xtal pu */
1524 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
1526 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
1528 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1532 * Avoid glitching the clock if GPRS is already using it.
1533 * We can't actually read the state of the PLLPD so we infer it
1534 * by the value of XTAL_PU which *is* readable via gpioin.
1536 if (on && (in & PCI_CFG_GPIO_XTAL))
1540 outen |= PCI_CFG_GPIO_XTAL;
1542 outen |= PCI_CFG_GPIO_PLL;
1545 /* turn primary xtal on */
1547 out |= PCI_CFG_GPIO_XTAL;
1549 out |= PCI_CFG_GPIO_PLL;
1550 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1551 sizeof(uint32), out);
1552 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1553 sizeof(uint32), outen);
1554 OSL_DELAY(XTAL_ON_DELAY);
1559 out &= ~PCI_CFG_GPIO_PLL;
1560 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1561 sizeof(uint32), out);
1566 out &= ~PCI_CFG_GPIO_XTAL;
1568 out |= PCI_CFG_GPIO_PLL;
1569 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1570 sizeof(uint32), out);
1571 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1572 sizeof(uint32), outen);
1583 * clock control policy function throught chipcommon
1585 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1586 * returns true if we are forcing fast clock
1587 * this is a wrapper over the next internal function
1588 * to allow flexible policy settings for outside caller
1590 bool si_clkctl_cc(si_t *sih, uint mode)
1596 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1600 if (PCI_FORCEHT(sii))
1601 return (mode == CLK_FAST);
1603 return _si_clkctl_cc(sii, mode);
1606 /* clk control mechanism through chipcommon, no policy checking */
1607 static bool _si_clkctl_cc(si_info_t *sii, uint mode)
1613 bool fast = SI_FAST(sii);
1615 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1616 if (sii->pub.ccrev < 6)
1619 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1620 ASSERT(sii->pub.ccrev != 10);
1623 INTR_OFF(sii, intr_val);
1624 origidx = sii->curidx;
1626 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1627 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1628 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1631 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
1632 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1636 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1640 case CLK_FAST: /* FORCEHT, fast (pll) clock */
1641 if (sii->pub.ccrev < 10) {
1642 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1643 si_clkctl_xtal(&sii->pub, XTAL, ON);
1644 SET_REG(sii->osh, &cc->slow_clk_ctl,
1645 (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1646 } else if (sii->pub.ccrev < 20) {
1647 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1649 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1652 /* wait for the PLL */
1653 if (PMUCTL_ENAB(&sii->pub)) {
1654 uint32 htavail = CCS_HTAVAIL;
1655 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
1656 == 0), PMU_MAX_TRANSITION_DLY);
1657 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1659 OSL_DELAY(PLL_DELAY);
1663 case CLK_DYNAMIC: /* enable dynamic clock control */
1664 if (sii->pub.ccrev < 10) {
1665 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1666 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
1667 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
1669 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
1671 /* for dynamic control, we have to release our xtal_pu "force on" */
1673 si_clkctl_xtal(&sii->pub, XTAL, OFF);
1674 } else if (sii->pub.ccrev < 20) {
1676 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
1678 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
1688 si_setcoreidx(&sii->pub, origidx);
1689 INTR_RESTORE(sii, intr_val);
1691 return (mode == CLK_FAST);
1694 /* Build device path. Support SI, PCI, and JTAG for now. */
1695 int BCMATTACHFN(si_devpath) (si_t *sih, char *path, int size) {
1698 ASSERT(path != NULL);
1699 ASSERT(size >= SI_DEVPATH_BUFSZ);
1701 if (!path || size <= 0)
1704 switch (BUSTYPE(sih->bustype)) {
1707 slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
1710 ASSERT((SI_INFO(sih))->osh != NULL);
1711 slen = snprintf(path, (size_t) size, "pci/%u/%u/",
1712 OSL_PCI_BUS((SI_INFO(sih))->osh),
1713 OSL_PCI_SLOT((SI_INFO(sih))->osh));
1718 SI_ERROR(("si_devpath: device 0 assumed\n"));
1719 slen = snprintf(path, (size_t) size, "sd/%u/", si_coreidx(sih));
1728 if (slen < 0 || slen >= size) {
1736 /* Get a variable, but only if it has a devpath prefix */
1737 char *BCMATTACHFN(si_getdevpathvar) (si_t *sih, const char *name) {
1738 char varname[SI_DEVPATH_BUFSZ + 32];
1740 si_devpathvar(sih, varname, sizeof(varname), name);
1742 return (getvar(NULL, varname));
1745 /* Get a variable, but only if it has a devpath prefix */
1746 int BCMATTACHFN(si_getdevpathintvar) (si_t *sih, const char *name) {
1747 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1748 return (getintvar(NULL, name));
1750 char varname[SI_DEVPATH_BUFSZ + 32];
1752 si_devpathvar(sih, varname, sizeof(varname), name);
1754 return (getintvar(NULL, varname));
1758 char *si_getnvramflvar(si_t *sih, const char *name)
1760 return (getvar(NULL, name));
1763 /* Concatenate the dev path with a varname into the given 'var' buffer
1764 * and return the 'var' pointer.
1765 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1766 * On overflow, the first char will be set to '\0'.
1768 static char *BCMATTACHFN(si_devpathvar) (si_t *sih, char *var, int len,
1772 if (!var || len <= 0)
1775 if (si_devpath(sih, var, len) == 0) {
1776 path_len = strlen(var);
1778 if (strlen(name) + 1 > (uint) (len - path_len))
1781 strncpy(var + path_len, name, len - path_len - 1);
1787 uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
1794 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1798 return pcicore_pciereg(sii->pch, offset, mask, val, type);
1802 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask,
1810 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1814 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
1818 /* return TRUE if PCIE capability exists in the pci config space */
1819 static bool si_ispcie(si_info_t *sii)
1823 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1827 pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1835 /* Wake-on-wireless-LAN (WOWL) support functions */
1836 /* Enable PME generation and disable clkreq */
1837 void si_pci_pmeen(si_t *sih)
1843 pcicore_pmeen(sii->pch);
1846 /* Return TRUE if PME status is set */
1847 bool si_pci_pmestat(si_t *sih)
1853 return pcicore_pmestat(sii->pch);
1856 /* Disable PME generation, clear the PME status bit if set */
1857 void si_pci_pmeclr(si_t *sih)
1863 pcicore_pmeclr(sii->pch);
1867 /* initialize the sdio core */
1868 void si_sdio_init(si_t *sih)
1870 si_info_t *sii = SI_INFO(sih);
1872 if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1873 (sih->buscoretype == SDIOD_CORE_ID)) {
1875 sdpcmd_regs_t *sdpregs;
1877 /* get the current core index */
1879 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1881 /* switch to sdio core */
1884 (sdpcmd_regs_t *) si_setcore(sih, PCMCIA_CORE_ID, 0)))
1886 (sdpcmd_regs_t *) si_setcore(sih, SDIOD_CORE_ID, 0);
1889 SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih->buscorerev, idx, sii->curidx, sdpregs));
1891 /* enable backplane error and core interrupts */
1892 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
1893 W_REG(sii->osh, &sdpregs->sbintmask,
1894 (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
1896 /* switch back to previous core */
1897 si_setcoreidx(sih, idx);
1900 /* enable interrupts */
1901 bcmsdh_intr_enable(sii->sdh);
1904 #endif /* BCMSDIO */
1906 bool BCMATTACHFN(si_pci_war16165) (si_t *sih) {
1911 return (PCI(sii) && (sih->buscorerev <= 10));
1914 /* Disable pcie_war_ovr for some platforms (sigh!)
1915 * This is for boards that have BFL2_PCIEWAR_OVR set
1916 * but are in systems that still want the benefits of ASPM
1917 * Note that this should be done AFTER si_doattach
1919 void si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
1928 pcie_war_ovr_aspm_update(sii->pch, aspm);
1931 /* back door for other module to override chippkg */
1932 void si_chippkg_set(si_t *sih, uint val)
1938 sii->pub.chippkg = val;
1941 void BCMINITFN(si_pci_up) (si_t *sih) {
1946 /* if not pci bus, we're done */
1947 if (BUSTYPE(sih->bustype) != PCI_BUS)
1950 if (PCI_FORCEHT(sii))
1951 _si_clkctl_cc(sii, CLK_FAST);
1954 pcicore_up(sii->pch, SI_PCIUP);
1958 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
1959 void BCMUNINITFN(si_pci_sleep) (si_t *sih) {
1964 pcicore_sleep(sii->pch);
1967 /* Unconfigure and/or apply various WARs when going down */
1968 void BCMINITFN(si_pci_down) (si_t *sih) {
1973 /* if not pci bus, we're done */
1974 if (BUSTYPE(sih->bustype) != PCI_BUS)
1977 /* release FORCEHT since chip is going to "down" state */
1978 if (PCI_FORCEHT(sii))
1979 _si_clkctl_cc(sii, CLK_DYNAMIC);
1981 pcicore_down(sii->pch, SI_PCIDOWN);
1985 * Configure the pci core for pci client (NIC) action
1986 * coremask is the bitvec of cores by index to be enabled.
1988 void BCMATTACHFN(si_pci_setup) (si_t *sih, uint coremask) {
1990 sbpciregs_t *pciregs = NULL;
1991 uint32 siflag = 0, w;
1996 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1999 ASSERT(PCI(sii) || PCIE(sii));
2000 ASSERT(sii->pub.buscoreidx != BADIDX);
2003 /* get current core index */
2006 /* we interrupt on this backplane flag number */
2007 siflag = si_flag(sih);
2009 /* switch over to pci core */
2011 (sbpciregs_t *) si_setcoreidx(sih, sii->pub.buscoreidx);
2015 * Enable sb->pci interrupts. Assume
2016 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2018 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2019 /* pci config write to set this core bit in PCIIntMask */
2020 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2021 w |= (coremask << PCI_SBIM_SHIFT);
2022 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2024 /* set sbintvec bit for our flag number */
2025 si_setint(sih, siflag);
2029 OR_REG(sii->osh, &pciregs->sbtopci2,
2030 (SBTOPCI_PREF | SBTOPCI_BURST));
2031 if (sii->pub.buscorerev >= 11) {
2032 OR_REG(sii->osh, &pciregs->sbtopci2,
2033 SBTOPCI_RC_READMULTI);
2034 w = R_REG(sii->osh, &pciregs->clkrun);
2035 W_REG(sii->osh, &pciregs->clkrun,
2036 (w | PCI_CLKRUN_DSBL));
2037 w = R_REG(sii->osh, &pciregs->clkrun);
2040 /* switch back to previous core */
2041 si_setcoreidx(sih, idx);
2045 uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2053 return pcie_clkreq(sii->pch, mask, val);
2056 uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2065 return pcie_lcreg(sii->pch, mask, val);
2068 /* indirect way to read pcie config regs */
2069 uint si_pcie_readreg(void *sih, uint addrtype, uint offset)
2071 return pcie_readreg(((si_info_t *) sih)->osh,
2072 (sbpcieregs_t *) PCIEREGS(((si_info_t *) sih)),
2077 * Fixup SROMless PCI device's configuration.
2078 * The current core may be changed upon return.
2080 int si_pci_fixcfg(si_t *sih)
2082 uint origidx, pciidx;
2083 sbpciregs_t *pciregs = NULL;
2084 sbpcieregs_t *pcieregs = NULL;
2086 uint16 val16, *reg16 = NULL;
2088 si_info_t *sii = SI_INFO(sih);
2090 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2092 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2093 /* save the current index */
2094 origidx = si_coreidx(&sii->pub);
2096 /* check 'pi' is correct and fix it if not */
2097 if (sii->pub.buscoretype == PCIE_CORE_ID) {
2099 (sbpcieregs_t *) si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2101 ASSERT(pcieregs != NULL);
2102 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2103 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
2104 pciregs = (sbpciregs_t *) si_setcore(&sii->pub, PCI_CORE_ID, 0);
2106 ASSERT(pciregs != NULL);
2107 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2109 pciidx = si_coreidx(&sii->pub);
2110 val16 = R_REG(sii->osh, reg16);
2111 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) {
2113 (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 &
2115 W_REG(sii->osh, reg16, val16);
2118 /* restore the original index */
2119 si_setcoreidx(&sii->pub, origidx);
2121 pcicore_hwup(sii->pch);
2125 /* change logical "focus" to the gpio core for optimized access */
2126 void *si_gpiosetcore(si_t *sih)
2128 return (si_setcoreidx(sih, SI_CC_IDX));
2131 /* mask&set gpiocontrol bits */
2132 uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2138 /* gpios could be shared on router platforms
2139 * ignore reservation if it's high priority (e.g., test apps)
2141 if ((priority != GPIO_HI_PRIORITY) &&
2142 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2143 mask = priority ? (si_gpioreservation & mask) :
2144 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2148 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2149 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2152 /* mask&set gpio output enable bits */
2153 uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2159 /* gpios could be shared on router platforms
2160 * ignore reservation if it's high priority (e.g., test apps)
2162 if ((priority != GPIO_HI_PRIORITY) &&
2163 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2164 mask = priority ? (si_gpioreservation & mask) :
2165 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2169 regoff = OFFSETOF(chipcregs_t, gpioouten);
2170 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2173 /* mask&set gpio output bits */
2174 uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2180 /* gpios could be shared on router platforms
2181 * ignore reservation if it's high priority (e.g., test apps)
2183 if ((priority != GPIO_HI_PRIORITY) &&
2184 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2185 mask = priority ? (si_gpioreservation & mask) :
2186 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2190 regoff = OFFSETOF(chipcregs_t, gpioout);
2191 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2194 /* reserve one gpio */
2195 uint32 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2201 /* only cores on SI_BUS share GPIO's and only applcation users need to
2202 * reserve/release GPIO
2204 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2205 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2208 /* make sure only one bit is set */
2209 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2210 ASSERT((gpio_bitmask)
2211 && !((gpio_bitmask) & (gpio_bitmask - 1)));
2215 /* already reserved */
2216 if (si_gpioreservation & gpio_bitmask)
2218 /* set reservation */
2219 si_gpioreservation |= gpio_bitmask;
2221 return si_gpioreservation;
2224 /* release one gpio */
2226 * releasing the gpio doesn't change the current value on the GPIO last write value
2227 * persists till some one overwrites it
2230 uint32 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2236 /* only cores on SI_BUS share GPIO's and only applcation users need to
2237 * reserve/release GPIO
2239 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2240 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2243 /* make sure only one bit is set */
2244 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2245 ASSERT((gpio_bitmask)
2246 && !((gpio_bitmask) & (gpio_bitmask - 1)));
2250 /* already released */
2251 if (!(si_gpioreservation & gpio_bitmask))
2254 /* clear reservation */
2255 si_gpioreservation &= ~gpio_bitmask;
2257 return si_gpioreservation;
2260 /* return the current gpioin register value */
2261 uint32 si_gpioin(si_t *sih)
2269 regoff = OFFSETOF(chipcregs_t, gpioin);
2270 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
2273 /* mask&set gpio interrupt polarity bits */
2274 uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2282 /* gpios could be shared on router platforms */
2283 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2284 mask = priority ? (si_gpioreservation & mask) :
2285 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2289 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2290 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2293 /* mask&set gpio interrupt mask bits */
2294 uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2302 /* gpios could be shared on router platforms */
2303 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2304 mask = priority ? (si_gpioreservation & mask) :
2305 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2309 regoff = OFFSETOF(chipcregs_t, gpiointmask);
2310 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2313 /* assign the gpio to an led */
2314 uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val)
2319 if (sih->ccrev < 16)
2322 /* gpio led powersave reg */
2324 (sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
2328 /* mask&set gpio timer val */
2329 uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2335 if (sih->ccrev < 16)
2338 return (si_corereg(sih, SI_CC_IDX,
2339 OFFSETOF(chipcregs_t, gpiotimerval), mask,
2343 uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2349 if (sih->ccrev < 20)
2353 (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
2354 OFFSETOF(chipcregs_t, gpiopullup));
2355 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2358 uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2364 if (sih->ccrev < 11)
2367 if (regtype == GPIO_REGEVT)
2368 offs = OFFSETOF(chipcregs_t, gpioevent);
2369 else if (regtype == GPIO_REGEVT_INTMSK)
2370 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2371 else if (regtype == GPIO_REGEVT_INTPOL)
2372 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2376 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2379 void *BCMATTACHFN(si_gpio_handler_register) (si_t *sih, uint32 event,
2380 bool level, gpio_handler_t cb,
2389 if (sih->ccrev < 11)
2392 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
2395 bzero(gi, sizeof(gpioh_item_t));
2401 gi->next = sii->gpioh_head;
2402 sii->gpioh_head = gi;
2404 return (void *)(gi);
2407 void BCMATTACHFN(si_gpio_handler_unregister) (si_t *sih, void *gpioh) {
2409 gpioh_item_t *p, *n;
2412 if (sih->ccrev < 11)
2415 ASSERT(sii->gpioh_head != NULL);
2416 if ((void *)sii->gpioh_head == gpioh) {
2417 sii->gpioh_head = sii->gpioh_head->next;
2418 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2421 p = sii->gpioh_head;
2424 if ((void *)n == gpioh) {
2426 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2434 ASSERT(0); /* Not found in list */
2437 void si_gpio_handler_process(si_t *sih)
2442 uint32 level = si_gpioin(sih);
2443 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
2446 for (h = sii->gpioh_head; h != NULL; h = h->next) {
2448 status = (h->level ? level : edge);
2450 if (status & h->event)
2451 h->handler(status, h->arg);
2455 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
2458 uint32 si_gpio_int_enable(si_t *sih, bool enable)
2464 if (sih->ccrev < 11)
2467 offs = OFFSETOF(chipcregs_t, intmask);
2469 (sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
2472 /* Return the size of the specified SOCRAM bank */
2474 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index,
2477 uint banksize, bankinfo;
2478 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2480 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
2482 W_REG(sii->osh, ®s->bankidx, bankidx);
2483 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2485 SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
2489 void si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
2494 sbsocramregs_t *regs;
2500 /* Block ints and save current core */
2501 INTR_OFF(sii, intr_val);
2502 origidx = si_coreidx(sih);
2505 *enable = *protect = 0;
2507 /* Switch to SOCRAM core */
2508 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2511 /* Get info for determining size */
2512 if (!(wasup = si_iscoreup(sih)))
2513 si_core_reset(sih, 0, 0);
2515 corerev = si_corerev(sih);
2516 if (corerev >= 10) {
2520 uint32 bankidx, bankinfo;
2522 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2523 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2524 SOCRAM_DEVRAMBANK_SHIFT);
2525 for (i = 0; i < nb; i++) {
2527 i | (SOCRAM_MEMTYPE_DEVRAM <<
2528 SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2529 W_REG(sii->osh, ®s->bankidx, bankidx);
2530 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2532 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
2533 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
2537 SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
2541 SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
2543 W_REG(sii->osh, ®s->bankinfo, bankinfo);
2544 } else if (i == 0) {
2545 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
2548 SOCRAM_BANKINFO_DEVRAMPRO_MASK)
2555 /* Return to previous state and core */
2557 si_core_disable(sih, 0);
2558 si_setcoreidx(sih, origidx);
2561 INTR_RESTORE(sii, intr_val);
2564 bool si_socdevram_pkg(si_t *sih)
2566 if (si_socdevram_size(sih) > 0)
2572 uint32 si_socdevram_size(si_t *sih)
2578 sbsocramregs_t *regs;
2584 /* Block ints and save current core */
2585 INTR_OFF(sii, intr_val);
2586 origidx = si_coreidx(sih);
2588 /* Switch to SOCRAM core */
2589 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2592 /* Get info for determining size */
2593 if (!(wasup = si_iscoreup(sih)))
2594 si_core_reset(sih, 0, 0);
2596 corerev = si_corerev(sih);
2597 if (corerev >= 10) {
2602 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2603 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2604 SOCRAM_DEVRAMBANK_SHIFT));
2605 for (i = 0; i < nb; i++)
2607 socram_banksize(sii, regs, i,
2608 SOCRAM_MEMTYPE_DEVRAM);
2611 /* Return to previous state and core */
2613 si_core_disable(sih, 0);
2614 si_setcoreidx(sih, origidx);
2617 INTR_RESTORE(sii, intr_val);
2622 /* Return the RAM size of the SOCRAM core */
2623 uint32 si_socram_size(si_t *sih)
2629 sbsocramregs_t *regs;
2637 /* Block ints and save current core */
2638 INTR_OFF(sii, intr_val);
2639 origidx = si_coreidx(sih);
2641 /* Switch to SOCRAM core */
2642 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2645 /* Get info for determining size */
2646 if (!(wasup = si_iscoreup(sih)))
2647 si_core_reset(sih, 0, 0);
2648 corerev = si_corerev(sih);
2649 coreinfo = R_REG(sii->osh, ®s->coreinfo);
2651 /* Calculate size from coreinfo based on rev */
2653 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
2654 else if (corerev < 3) {
2655 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
2656 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2657 } else if ((corerev <= 7) || (corerev == 12)) {
2658 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2659 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
2660 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
2663 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
2665 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
2668 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2669 for (i = 0; i < nb; i++)
2671 socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
2674 /* Return to previous state and core */
2676 si_core_disable(sih, 0);
2677 si_setcoreidx(sih, origidx);
2680 INTR_RESTORE(sii, intr_val);
2685 void si_chipcontrl_epa4331(si_t *sih, bool on)
2693 origidx = si_coreidx(sih);
2695 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2697 val = R_REG(sii->osh, &cc->chipcontrol);
2700 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
2701 /* Ext PA Controls for 4331 12x9 Package */
2702 W_REG(sii->osh, &cc->chipcontrol, val |
2703 (CCTRL4331_EXTPA_EN |
2704 CCTRL4331_EXTPA_ON_GPIO2_5));
2706 /* Ext PA Controls for 4331 12x12 Package */
2707 W_REG(sii->osh, &cc->chipcontrol,
2708 val | (CCTRL4331_EXTPA_EN));
2711 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2712 W_REG(sii->osh, &cc->chipcontrol, val);
2715 si_setcoreidx(sih, origidx);
2718 /* Enable BT-COEX & Ex-PA for 4313 */
2719 void si_epa_4313war(si_t *sih)
2726 origidx = si_coreidx(sih);
2728 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2731 W_REG(sii->osh, &cc->gpiocontrol,
2732 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2734 si_setcoreidx(sih, origidx);
2737 /* check if the device is removed */
2738 bool si_deviceremoved(si_t *sih)
2745 switch (BUSTYPE(sih->bustype)) {
2747 ASSERT(sii->osh != NULL);
2748 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
2749 if ((w & 0xFFFF) != VENDOR_BROADCOM)
2756 bool si_is_sprom_available(si_t *sih)
2758 if (sih->ccrev >= 31) {
2764 if ((sih->cccaps & CC_CAP_SROM) == 0)
2768 origidx = sii->curidx;
2769 cc = si_setcoreidx(sih, SI_CC_IDX);
2770 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
2771 si_setcoreidx(sih, origidx);
2772 return (sromctrl & SRC_PRESENT);
2775 switch (CHIPID(sih->chip)) {
2776 case BCM4329_CHIP_ID:
2777 return (sih->chipst & CST4329_SPROM_SEL) != 0;
2778 case BCM4319_CHIP_ID:
2779 return (sih->chipst & CST4319_SPROM_SEL) != 0;
2780 case BCM4336_CHIP_ID:
2781 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
2782 case BCM4330_CHIP_ID:
2783 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
2784 case BCM4313_CHIP_ID:
2785 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
2786 case BCM4331_CHIP_ID:
2787 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
2793 bool si_is_otp_disabled(si_t *sih)
2795 switch (CHIPID(sih->chip)) {
2796 case BCM4329_CHIP_ID:
2797 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
2799 case BCM4319_CHIP_ID:
2800 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
2802 case BCM4336_CHIP_ID:
2803 return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
2804 case BCM4330_CHIP_ID:
2805 return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
2806 case BCM4313_CHIP_ID:
2807 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
2808 /* These chips always have their OTP on */
2809 case BCM43224_CHIP_ID:
2810 case BCM43225_CHIP_ID:
2811 case BCM43421_CHIP_ID:
2812 case BCM43235_CHIP_ID:
2813 case BCM43236_CHIP_ID:
2814 case BCM43238_CHIP_ID:
2815 case BCM4331_CHIP_ID:
2821 bool si_is_otp_powered(si_t *sih)
2823 if (PMUCTL_ENAB(sih))
2824 return si_pmu_is_otp_powered(sih, si_osh(sih));
2828 void si_otp_power(si_t *sih, bool on)
2830 if (PMUCTL_ENAB(sih))
2831 si_pmu_otp_power(sih, si_osh(sih), on);
2837 si_is_sprom_enabled(si_t *sih)
2839 BCMATTACHFN(si_is_sprom_enabled) (si_t *sih)
2848 si_sprom_enable(si_t *sih, bool enable)
2850 BCMATTACHFN(si_sprom_enable) (si_t *sih, bool enable)
2853 if (PMUCTL_ENAB(sih))
2854 si_pmu_sprom_enable(sih, si_osh(sih), enable);
2857 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
2858 int si_cis_source(si_t *sih)
2860 /* Many chips have the same mapping of their chipstatus field */
2861 static const uint cis_sel[] =
2862 { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
2863 static const uint cis_43236_sel[] =
2864 { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_OTP };
2866 /* PCI chips use SROM format instead of CIS */
2867 if (BUSTYPE(sih->bustype) == PCI_BUS)
2868 return BCME_NOTFOUND;
2870 switch (CHIPID(sih->chip)) {
2871 case BCM43235_CHIP_ID:
2872 case BCM43236_CHIP_ID:
2873 case BCM43238_CHIP_ID:{
2876 chipst & CST4322_SPROM_OTP_SEL_MASK) >>
2877 CST4322_SPROM_OTP_SEL_SHIFT;
2879 sizeof(cis_sel)) ? CIS_DEFAULT :
2880 cis_43236_sel[strap]);
2883 case BCM4329_CHIP_ID:
2884 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >=
2885 sizeof(cis_sel)) ? CIS_DEFAULT : cis_sel[(sih->
2887 CST4329_SPROM_OTP_SEL_MASK)];
2888 case BCM4319_CHIP_ID:{
2891 chipst & CST4319_SPROM_OTP_SEL_MASK) >>
2892 CST4319_SPROM_OTP_SEL_SHIFT);
2893 return (cis_sel4319 >=
2894 sizeof(cis_sel)) ? CIS_DEFAULT :
2895 cis_sel[cis_sel4319];
2897 case BCM4336_CHIP_ID:{
2898 if (sih->chipst & CST4336_SPROM_PRESENT)
2900 if (sih->chipst & CST4336_OTP_PRESENT)
2904 case BCM4330_CHIP_ID:{
2905 if (sih->chipst & CST4330_SPROM_PRESENT)
2907 if (sih->chipst & CST4330_OTP_PRESENT)