Staging: brcm80211: s/ushort/unsigned short/
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / brcm80211 / util / siutils.c
blob1a4c2b654997afa1c58c46ed60388a18db0cec48
1 /*
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.
17 #include <typedefs.h>
18 #include <bcmdefs.h>
19 #include <osl.h>
20 #include <linux/kernel.h>
21 #include <linux/string.h>
22 #include <linuxver.h>
23 #include <bcmutils.h>
24 #include <siutils.h>
25 #include <bcmdevs.h>
26 #include <hndsoc.h>
27 #include <sbchipc.h>
28 #include <pci_core.h>
29 #include <pcie_core.h>
30 #include <nicpci.h>
31 #include <bcmnvram.h>
32 #include <bcmsrom.h>
33 #include <hndtcam.h>
34 #include <pcicfg.h>
35 #include <sbsocram.h>
36 #ifdef BCMSDIO
37 #include <bcmsdh.h>
38 #include <sdio.h>
39 #include <sbsdio.h>
40 #include <sbhnddma.h>
41 #include <sbsdpcmdev.h>
42 #include <bcmsdpcm.h>
43 #endif /* BCMSDIO */
44 #include <hndpmu.h>
46 /* this file now contains only definitions for sb functions, only necessary
47 *for devices using Sonics backplanes (bcm4329)
50 /* if an amba SDIO device is supported, please further restrict the inclusion
51 * of this file
53 #ifdef BCMSDIO
54 #include "siutils_priv.h"
55 #endif
57 /* local prototypes */
58 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
59 void *regs, uint bustype, void *sdh, char **vars,
60 uint *varsz);
61 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
62 void *sdh);
63 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
64 uint32 savewin, uint *origidx, void *regs);
65 static void si_nvram_process(si_info_t *sii, char *pvars);
67 /* dev path concatenation util */
68 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
69 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
70 static bool si_ispcie(si_info_t *sii);
71 static uint BCMINITFN(socram_banksize) (si_info_t *sii, sbsocramregs_t *r,
72 u8 idx, u8 mtype);
74 /* global variable to indicate reservation/release of gpio's */
75 static uint32 si_gpioreservation;
77 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
80 * Allocate a si handle.
81 * devid - pci device id (used to determine chip#)
82 * osh - opaque OS handle
83 * regs - virtual address of initial core registers
84 * bustype - pci/sb/sdio/etc
85 * vars - pointer to a pointer area for "environment" variables
86 * varsz - pointer to int to return the size of the vars
88 si_t *BCMATTACHFN(si_attach) (uint devid, osl_t *osh, void *regs,
89 uint bustype, void *sdh, char **vars,
90 uint *varsz) {
91 si_info_t *sii;
93 /* alloc si_info_t */
94 sii = MALLOC(osh, sizeof(si_info_t));
95 if (sii == NULL) {
96 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n",
97 MALLOCED(osh)));
98 return NULL;
101 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
102 NULL) {
103 MFREE(osh, sii, sizeof(si_info_t));
104 return NULL;
106 sii->vars = vars ? *vars : NULL;
107 sii->varsz = varsz ? *varsz : 0;
109 return (si_t *) sii;
112 /* global kernel resource */
113 static si_info_t ksii;
115 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
117 static bool
118 BCMATTACHFN(si_buscore_prep) (si_info_t *sii, uint bustype, uint devid,
119 void *sdh) {
121 #ifndef BRCM_FULLMAC
122 /* kludge to enable the clock on the 4306 which lacks a slowclock */
123 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
124 si_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
125 #endif
127 #if defined(BCMSDIO)
128 if (BUSTYPE(bustype) == SDIO_BUS) {
129 int err;
130 u8 clkset;
132 /* Try forcing SDIO core to do ALPAvail request only */
133 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
134 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
135 clkset, &err);
136 if (!err) {
137 u8 clkval;
139 /* If register supported, wait for ALPAvail and then force ALP */
140 clkval =
141 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
142 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
143 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
144 SPINWAIT(((clkval =
145 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
146 SBSDIO_FUNC1_CHIPCLKCSR,
147 NULL)),
148 !SBSDIO_ALPAV(clkval)),
149 PMU_MAX_TRANSITION_DLY);
150 if (!SBSDIO_ALPAV(clkval)) {
151 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval));
152 return FALSE;
154 clkset =
155 SBSDIO_FORCE_HW_CLKREQ_OFF |
156 SBSDIO_FORCE_ALP;
157 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
158 SBSDIO_FUNC1_CHIPCLKCSR,
159 clkset, &err);
160 OSL_DELAY(65);
164 /* Also, disable the extra SDIO pull-ups */
165 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
166 NULL);
168 #endif /* defined(BCMSDIO) */
170 return TRUE;
173 static bool
174 BCMATTACHFN(si_buscore_setup) (si_info_t *sii, chipcregs_t *cc, uint bustype,
175 uint32 savewin, uint *origidx, void *regs) {
176 bool pci, pcie;
177 uint i;
178 uint pciidx, pcieidx, pcirev, pcierev;
180 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
181 ASSERT((uintptr) cc);
183 /* get chipcommon rev */
184 sii->pub.ccrev = (int)si_corerev(&sii->pub);
186 /* get chipcommon chipstatus */
187 if (sii->pub.ccrev >= 11)
188 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
190 /* get chipcommon capabilites */
191 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
192 /* get chipcommon extended capabilities */
194 #ifndef BRCM_FULLMAC
195 if (sii->pub.ccrev >= 35)
196 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
197 #endif
198 /* get pmu rev and caps */
199 if (sii->pub.cccaps & CC_CAP_PMU) {
200 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
201 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
205 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
206 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
207 sii->pub.pmucaps));
210 /* figure out bus/orignal core idx */
211 sii->pub.buscoretype = NODEV_CORE_ID;
212 sii->pub.buscorerev = NOREV;
213 sii->pub.buscoreidx = BADIDX;
215 pci = pcie = FALSE;
216 pcirev = pcierev = NOREV;
217 pciidx = pcieidx = BADIDX;
219 for (i = 0; i < sii->numcores; i++) {
220 uint cid, crev;
222 si_setcoreidx(&sii->pub, i);
223 cid = si_coreid(&sii->pub);
224 crev = si_corerev(&sii->pub);
226 /* Display cores found */
227 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
228 i, cid, crev, sii->coresba[i], sii->regs[i]));
230 if (BUSTYPE(bustype) == PCI_BUS) {
231 if (cid == PCI_CORE_ID) {
232 pciidx = i;
233 pcirev = crev;
234 pci = TRUE;
235 } else if (cid == PCIE_CORE_ID) {
236 pcieidx = i;
237 pcierev = crev;
238 pcie = TRUE;
241 #ifdef BCMSDIO
242 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
243 (BUSTYPE(bustype) == SPI_BUS)) &&
244 ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) {
245 sii->pub.buscorerev = crev;
246 sii->pub.buscoretype = cid;
247 sii->pub.buscoreidx = i;
249 #endif /* BCMSDIO */
251 /* find the core idx before entering this func. */
252 if ((savewin && (savewin == sii->coresba[i])) ||
253 (regs == sii->regs[i]))
254 *origidx = i;
257 #ifdef BRCM_FULLMAC
258 SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
259 sii->pub.buscoretype, sii->pub.buscorerev));
261 /* Make sure any on-chip ARM is off (in case strapping is wrong),
262 * or downloaded code was
263 * already running.
265 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
266 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
267 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
268 si_core_disable(&sii->pub, 0);
270 #else
271 if (pci && pcie) {
272 if (si_ispcie(sii))
273 pci = FALSE;
274 else
275 pcie = FALSE;
277 if (pci) {
278 sii->pub.buscoretype = PCI_CORE_ID;
279 sii->pub.buscorerev = pcirev;
280 sii->pub.buscoreidx = pciidx;
281 } else if (pcie) {
282 sii->pub.buscoretype = PCIE_CORE_ID;
283 sii->pub.buscorerev = pcierev;
284 sii->pub.buscoreidx = pcieidx;
287 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
288 sii->pub.buscoretype, sii->pub.buscorerev));
290 /* fixup necessary chip/core configurations */
291 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
292 if (SI_FAST(sii)) {
293 if (!sii->pch) {
294 sii->pch = (void *)(uintptr)pcicore_init(
295 &sii->pub, sii->osh,
296 (void *)PCIEREGS(sii));
297 if (sii->pch == NULL)
298 return FALSE;
301 if (si_pci_fixcfg(&sii->pub)) {
302 SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
303 return FALSE;
306 #endif
307 /* return to the original core */
308 si_setcoreidx(&sii->pub, *origidx);
310 return TRUE;
313 static __used void BCMATTACHFN(si_nvram_process) (si_info_t *sii, char *pvars)
315 uint w = 0;
317 /* get boardtype and boardrev */
318 switch (BUSTYPE(sii->pub.bustype)) {
319 case PCI_BUS:
320 /* do a pci config read to get subsystem id and subvendor id */
321 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
322 /* Let nvram variables override subsystem Vend/ID */
323 sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub,
324 "boardvendor");
325 if (sii->pub.boardvendor == 0)
326 sii->pub.boardvendor = w & 0xffff;
327 else
328 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii->pub.boardvendor, w & 0xffff));
329 sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub,
330 "boardtype");
331 if (sii->pub.boardtype == 0)
332 sii->pub.boardtype = (w >> 16) & 0xffff;
333 else
334 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii->pub.boardtype, (w >> 16) & 0xffff));
335 break;
337 #ifdef BCMSDIO
338 case SDIO_BUS:
339 #endif
340 sii->pub.boardvendor = getintvar(pvars, "manfid");
341 sii->pub.boardtype = getintvar(pvars, "prodid");
342 break;
344 #ifdef BCMSDIO
345 case SPI_BUS:
346 sii->pub.boardvendor = VENDOR_BROADCOM;
347 sii->pub.boardtype = SPI_BOARD;
348 break;
349 #endif
351 case SI_BUS:
352 case JTAG_BUS:
353 sii->pub.boardvendor = VENDOR_BROADCOM;
354 sii->pub.boardtype = getintvar(pvars, "prodid");
355 if (pvars == NULL || (sii->pub.boardtype == 0)) {
356 sii->pub.boardtype = getintvar(NULL, "boardtype");
357 if (sii->pub.boardtype == 0)
358 sii->pub.boardtype = 0xffff;
360 break;
363 if (sii->pub.boardtype == 0) {
364 SI_ERROR(("si_doattach: unknown board type\n"));
365 ASSERT(sii->pub.boardtype);
368 sii->pub.boardflags = getintvar(pvars, "boardflags");
371 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
372 /* this has been customized for the bcm 4329 ONLY */
373 #ifdef BCMSDIO
374 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
375 osl_t *osh, void *regs,
376 uint bustype, void *sdh,
377 char **vars, uint *varsz) {
378 struct si_pub *sih = &sii->pub;
379 uint32 w, savewin;
380 chipcregs_t *cc;
381 char *pvars = NULL;
382 uint origidx;
384 ASSERT(GOODREGS(regs));
386 bzero((unsigned char *) sii, sizeof(si_info_t));
388 savewin = 0;
390 sih->buscoreidx = BADIDX;
392 sii->curmap = regs;
393 sii->sdh = sdh;
394 sii->osh = osh;
396 /* find Chipcommon address */
397 cc = (chipcregs_t *) sii->curmap;
398 sih->bustype = bustype;
400 if (bustype != BUSTYPE(bustype)) {
401 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
402 return NULL;
405 /* bus/core/clk setup for register access */
406 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
407 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
408 bustype));
409 return NULL;
412 /* ChipID recognition.
413 * We assume we can read chipid at offset 0 from the regs arg.
414 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
415 * some way of recognizing them needs to be added here.
417 w = R_REG(osh, &cc->chipid);
418 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
419 /* Might as wll fill in chip id rev & pkg */
420 sih->chip = w & CID_ID_MASK;
421 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
422 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
424 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) &&
425 (sih->chippkg != BCM4329_289PIN_PKG_ID))
426 sih->chippkg = BCM4329_182PIN_PKG_ID;
428 sih->issim = IS_SIM(sih->chippkg);
430 /* scan for cores */
431 /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
432 sb_scan(&sii->pub, regs, devid);
434 /* no cores found, bail out */
435 if (sii->numcores == 0) {
436 SI_ERROR(("si_doattach: could not find any cores\n"));
437 return NULL;
439 /* bus/core/clk setup */
440 origidx = SI_CC_IDX;
441 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
442 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
443 goto exit;
446 #ifdef BRCM_FULLMAC
447 pvars = NULL;
448 #else
449 /* Init nvram from flash if it exists */
450 nvram_init((void *)&(sii->pub));
452 /* Init nvram from sprom/otp if they exist */
453 if (srom_var_init
454 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
455 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
456 goto exit;
458 pvars = vars ? *vars : NULL;
459 si_nvram_process(sii, pvars);
460 #endif
462 /* === NVRAM, clock is ready === */
464 #ifdef BRCM_FULLMAC
465 if (sii->pub.ccrev >= 20) {
466 #endif
467 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
468 W_REG(osh, &cc->gpiopullup, 0);
469 W_REG(osh, &cc->gpiopulldown, 0);
470 sb_setcoreidx(sih, origidx);
471 #ifdef BRCM_FULLMAC
473 #endif
475 #ifndef BRCM_FULLMAC
476 /* PMU specific initializations */
477 if (PMUCTL_ENAB(sih)) {
478 uint32 xtalfreq;
479 si_pmu_init(sih, sii->osh);
480 si_pmu_chip_init(sih, sii->osh);
481 xtalfreq = getintvar(pvars, "xtalfreq");
482 /* If xtalfreq var not available, try to measure it */
483 if (xtalfreq == 0)
484 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
485 si_pmu_pll_init(sih, sii->osh, xtalfreq);
486 si_pmu_res_init(sih, sii->osh);
487 si_pmu_swreg_init(sih, sii->osh);
490 /* setup the GPIO based LED powersave register */
491 w = getintvar(pvars, "leddc");
492 if (w == 0)
493 w = DEFAULT_GPIOTIMERVAL;
494 sb_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
496 #ifdef BCMDBG
497 /* clear any previous epidiag-induced target abort */
498 sb_taclear(sih, FALSE);
499 #endif /* BCMDBG */
500 #endif
502 return sii;
504 exit:
505 return NULL;
508 #else /* BCMSDIO */
509 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
510 osl_t *osh, void *regs,
511 uint bustype, void *sdh,
512 char **vars, uint *varsz) {
513 struct si_pub *sih = &sii->pub;
514 uint32 w, savewin;
515 chipcregs_t *cc;
516 char *pvars = NULL;
517 uint origidx;
519 ASSERT(GOODREGS(regs));
521 bzero((unsigned char *) sii, sizeof(si_info_t));
523 savewin = 0;
525 sih->buscoreidx = BADIDX;
527 sii->curmap = regs;
528 sii->sdh = sdh;
529 sii->osh = osh;
531 /* check to see if we are a si core mimic'ing a pci core */
532 if ((bustype == PCI_BUS) &&
533 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) ==
534 0xffffffff)) {
535 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " "devid:0x%x\n", __func__, devid));
536 bustype = SI_BUS;
539 /* find Chipcommon address */
540 if (bustype == PCI_BUS) {
541 savewin =
542 OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
543 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
544 savewin = SI_ENUM_BASE;
545 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
546 cc = (chipcregs_t *) regs;
547 } else {
548 cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
551 sih->bustype = bustype;
552 if (bustype != BUSTYPE(bustype)) {
553 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
554 return NULL;
557 /* bus/core/clk setup for register access */
558 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
559 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
560 bustype));
561 return NULL;
564 /* ChipID recognition.
565 * We assume we can read chipid at offset 0 from the regs arg.
566 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
567 * some way of recognizing them needs to be added here.
569 w = R_REG(osh, &cc->chipid);
570 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
571 /* Might as wll fill in chip id rev & pkg */
572 sih->chip = w & CID_ID_MASK;
573 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
574 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
576 sih->issim = IS_SIM(sih->chippkg);
578 /* scan for cores */
579 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
580 SI_MSG(("Found chip type AI (0x%08x)\n", w));
581 /* pass chipc address instead of original core base */
582 ai_scan(&sii->pub, (void *)(uintptr) cc, devid);
583 } else {
584 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
585 return NULL;
587 /* no cores found, bail out */
588 if (sii->numcores == 0) {
589 SI_ERROR(("si_doattach: could not find any cores\n"));
590 return NULL;
592 /* bus/core/clk setup */
593 origidx = SI_CC_IDX;
594 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
595 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
596 goto exit;
599 /* assume current core is CC */
600 if ((sii->pub.ccrev == 0x25)
602 ((CHIPID(sih->chip) == BCM43236_CHIP_ID
603 || CHIPID(sih->chip) == BCM43235_CHIP_ID
604 || CHIPID(sih->chip) == BCM43238_CHIP_ID)
605 && (CHIPREV(sii->pub.chiprev) <= 2))) {
607 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
608 uint clkdiv;
609 clkdiv = R_REG(osh, &cc->clkdiv);
610 /* otp_clk_div is even number, 120/14 < 9mhz */
611 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
612 W_REG(osh, &cc->clkdiv, clkdiv);
613 SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
615 OSL_DELAY(10);
618 /* Init nvram from flash if it exists */
619 nvram_init((void *)&(sii->pub));
621 /* Init nvram from sprom/otp if they exist */
622 if (srom_var_init
623 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
624 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
625 goto exit;
627 pvars = vars ? *vars : NULL;
628 si_nvram_process(sii, pvars);
630 /* === NVRAM, clock is ready === */
631 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
632 W_REG(osh, &cc->gpiopullup, 0);
633 W_REG(osh, &cc->gpiopulldown, 0);
634 si_setcoreidx(sih, origidx);
636 /* PMU specific initializations */
637 if (PMUCTL_ENAB(sih)) {
638 uint32 xtalfreq;
639 si_pmu_init(sih, sii->osh);
640 si_pmu_chip_init(sih, sii->osh);
641 xtalfreq = getintvar(pvars, "xtalfreq");
642 /* If xtalfreq var not available, try to measure it */
643 if (xtalfreq == 0)
644 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
645 si_pmu_pll_init(sih, sii->osh, xtalfreq);
646 si_pmu_res_init(sih, sii->osh);
647 si_pmu_swreg_init(sih, sii->osh);
650 /* setup the GPIO based LED powersave register */
651 w = getintvar(pvars, "leddc");
652 if (w == 0)
653 w = DEFAULT_GPIOTIMERVAL;
654 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
656 if (PCIE(sii)) {
657 ASSERT(sii->pch != NULL);
658 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
661 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
662 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
663 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
664 if (CHIPREV(sih->chiprev) == 0) {
665 SI_MSG(("Applying 43224A0 WARs\n"));
666 si_corereg(sih, SI_CC_IDX,
667 OFFSETOF(chipcregs_t, chipcontrol),
668 CCTRL43224_GPIO_TOGGLE,
669 CCTRL43224_GPIO_TOGGLE);
670 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
671 CCTRL_43224A0_12MA_LED_DRIVE);
673 if (CHIPREV(sih->chiprev) >= 1) {
674 SI_MSG(("Applying 43224B0+ WARs\n"));
675 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
676 CCTRL_43224B0_12MA_LED_DRIVE);
680 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
681 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
682 SI_MSG(("Applying 4313 WARs\n"));
683 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
684 CCTRL_4313_12MA_LED_DRIVE);
687 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
688 /* Enable Ext PA lines depending on chip package option */
689 si_chipcontrl_epa4331(sih, TRUE);
692 return sii;
693 exit:
694 if (BUSTYPE(sih->bustype) == PCI_BUS) {
695 if (sii->pch)
696 pcicore_deinit(sii->pch);
697 sii->pch = NULL;
700 return NULL;
702 #endif /* BCMSDIO */
704 /* may be called with core in reset */
705 void BCMATTACHFN(si_detach) (si_t *sih)
707 si_info_t *sii;
708 uint idx;
710 struct si_pub *si_local = NULL;
711 bcopy(&sih, &si_local, sizeof(si_t **));
713 sii = SI_INFO(sih);
715 if (sii == NULL)
716 return;
718 if (BUSTYPE(sih->bustype) == SI_BUS)
719 for (idx = 0; idx < SI_MAXCORES; idx++)
720 if (sii->regs[idx]) {
721 REG_UNMAP(sii->regs[idx]);
722 sii->regs[idx] = NULL;
725 #ifndef BRCM_FULLMAC
726 nvram_exit((void *)si_local); /* free up nvram buffers */
728 if (BUSTYPE(sih->bustype) == PCI_BUS) {
729 if (sii->pch)
730 pcicore_deinit(sii->pch);
731 sii->pch = NULL;
733 #endif
734 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
735 if (sii != &ksii)
736 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
737 MFREE(sii->osh, sii, sizeof(si_info_t));
740 void *si_osh(si_t *sih)
742 si_info_t *sii;
744 sii = SI_INFO(sih);
745 return sii->osh;
748 void si_setosh(si_t *sih, osl_t *osh)
750 si_info_t *sii;
752 sii = SI_INFO(sih);
753 if (sii->osh != NULL) {
754 SI_ERROR(("osh is already set....\n"));
755 ASSERT(!sii->osh);
757 sii->osh = osh;
760 /* register driver interrupt disabling and restoring callback functions */
761 void
762 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
763 void *intrsenabled_fn, void *intr_arg)
765 si_info_t *sii;
767 sii = SI_INFO(sih);
768 sii->intr_arg = intr_arg;
769 sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
770 sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
771 sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
772 /* save current core id. when this function called, the current core
773 * must be the core which provides driver functions(il, et, wl, etc.)
775 sii->dev_coreid = sii->coreid[sii->curidx];
778 void si_deregister_intr_callback(si_t *sih)
780 si_info_t *sii;
782 sii = SI_INFO(sih);
783 sii->intrsoff_fn = NULL;
786 uint si_intflag(si_t *sih)
788 si_info_t *sii = SI_INFO(sih);
790 if (CHIPTYPE(sih->socitype) == SOCI_AI)
791 return R_REG(sii->osh,
792 ((uint32 *) (uintptr) (sii->oob_router +
793 OOB_STATUSA)));
794 else {
795 ASSERT(0);
796 return 0;
800 uint si_flag(si_t *sih)
802 if (CHIPTYPE(sih->socitype) == SOCI_AI)
803 return ai_flag(sih);
804 else {
805 ASSERT(0);
806 return 0;
810 void si_setint(si_t *sih, int siflag)
812 if (CHIPTYPE(sih->socitype) == SOCI_AI)
813 ai_setint(sih, siflag);
814 else
815 ASSERT(0);
818 #ifndef BCMSDIO
819 uint si_coreid(si_t *sih)
821 si_info_t *sii;
823 sii = SI_INFO(sih);
824 return sii->coreid[sii->curidx];
826 #endif
828 uint si_coreidx(si_t *sih)
830 si_info_t *sii;
832 sii = SI_INFO(sih);
833 return sii->curidx;
836 /* return the core-type instantiation # of the current core */
837 uint si_coreunit(si_t *sih)
839 si_info_t *sii;
840 uint idx;
841 uint coreid;
842 uint coreunit;
843 uint i;
845 sii = SI_INFO(sih);
846 coreunit = 0;
848 idx = sii->curidx;
850 ASSERT(GOODREGS(sii->curmap));
851 coreid = si_coreid(sih);
853 /* count the cores of our type */
854 for (i = 0; i < idx; i++)
855 if (sii->coreid[i] == coreid)
856 coreunit++;
858 return coreunit;
861 uint si_corevendor(si_t *sih)
863 if (CHIPTYPE(sih->socitype) == SOCI_AI)
864 return ai_corevendor(sih);
865 else {
866 ASSERT(0);
867 return 0;
871 bool si_backplane64(si_t *sih)
873 return (sih->cccaps & CC_CAP_BKPLN64) != 0;
876 #ifndef BCMSDIO
877 uint si_corerev(si_t *sih)
879 if (CHIPTYPE(sih->socitype) == SOCI_AI)
880 return ai_corerev(sih);
881 else {
882 ASSERT(0);
883 return 0;
886 #endif
888 /* return index of coreid or BADIDX if not found */
889 uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
891 si_info_t *sii;
892 uint found;
893 uint i;
895 sii = SI_INFO(sih);
897 found = 0;
899 for (i = 0; i < sii->numcores; i++)
900 if (sii->coreid[i] == coreid) {
901 if (found == coreunit)
902 return i;
903 found++;
906 return BADIDX;
909 /* return list of found cores */
910 uint si_corelist(si_t *sih, uint coreid[])
912 si_info_t *sii;
914 sii = SI_INFO(sih);
916 bcopy((unsigned char *) sii->coreid, (unsigned char *) coreid,
917 (sii->numcores * sizeof(uint)));
918 return sii->numcores;
921 /* return current register mapping */
922 void *si_coreregs(si_t *sih)
924 si_info_t *sii;
926 sii = SI_INFO(sih);
927 ASSERT(GOODREGS(sii->curmap));
929 return sii->curmap;
933 * This function changes logical "focus" to the indicated core;
934 * must be called with interrupts off.
935 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
937 void *si_setcore(si_t *sih, uint coreid, uint coreunit)
939 uint idx;
941 idx = si_findcoreidx(sih, coreid, coreunit);
942 if (!GOODIDX(idx))
943 return NULL;
945 if (CHIPTYPE(sih->socitype) == SOCI_AI)
946 return ai_setcoreidx(sih, idx);
947 else {
948 #ifdef BCMSDIO
949 return sb_setcoreidx(sih, idx);
950 #else
951 ASSERT(0);
952 return NULL;
953 #endif
957 #ifndef BCMSDIO
958 void *si_setcoreidx(si_t *sih, uint coreidx)
960 if (CHIPTYPE(sih->socitype) == SOCI_AI)
961 return ai_setcoreidx(sih, coreidx);
962 else {
963 ASSERT(0);
964 return NULL;
967 #endif
969 /* Turn off interrupt as required by sb_setcore, before switch core */
970 void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
972 void *cc;
973 si_info_t *sii;
975 sii = SI_INFO(sih);
977 if (SI_FAST(sii)) {
978 /* Overloading the origidx variable to remember the coreid,
979 * this works because the core ids cannot be confused with
980 * core indices.
982 *origidx = coreid;
983 if (coreid == CC_CORE_ID)
984 return (void *)CCREGS_FAST(sii);
985 else if (coreid == sih->buscoretype)
986 return (void *)PCIEREGS(sii);
988 INTR_OFF(sii, *intr_val);
989 *origidx = sii->curidx;
990 cc = si_setcore(sih, coreid, 0);
991 ASSERT(cc != NULL);
993 return cc;
996 /* restore coreidx and restore interrupt */
997 void si_restore_core(si_t *sih, uint coreid, uint intr_val)
999 si_info_t *sii;
1001 sii = SI_INFO(sih);
1002 if (SI_FAST(sii)
1003 && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1004 return;
1006 si_setcoreidx(sih, coreid);
1007 INTR_RESTORE(sii, intr_val);
1010 int si_numaddrspaces(si_t *sih)
1012 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1013 return ai_numaddrspaces(sih);
1014 else {
1015 ASSERT(0);
1016 return 0;
1020 uint32 si_addrspace(si_t *sih, uint asidx)
1022 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1023 return ai_addrspace(sih, asidx);
1024 else {
1025 ASSERT(0);
1026 return 0;
1030 uint32 si_addrspacesize(si_t *sih, uint asidx)
1032 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1033 return ai_addrspacesize(sih, asidx);
1034 else {
1035 ASSERT(0);
1036 return 0;
1040 uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1042 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1043 return ai_core_cflags(sih, mask, val);
1044 else {
1045 ASSERT(0);
1046 return 0;
1050 void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1052 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1053 ai_core_cflags_wo(sih, mask, val);
1054 else
1055 ASSERT(0);
1058 uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1060 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1061 return ai_core_sflags(sih, mask, val);
1062 else {
1063 ASSERT(0);
1064 return 0;
1068 bool si_iscoreup(si_t *sih)
1070 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1071 return ai_iscoreup(sih);
1072 else {
1073 #ifdef BCMSDIO
1074 return sb_iscoreup(sih);
1075 #else
1076 ASSERT(0);
1077 return FALSE;
1078 #endif
1082 void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1084 /* only for 4319, no requirement for SOCI_SB */
1085 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1086 ai_write_wrap_reg(sih, offset, val);
1090 uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1093 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1094 return ai_corereg(sih, coreidx, regoff, mask, val);
1095 else {
1096 #ifdef BCMSDIO
1097 return sb_corereg(sih, coreidx, regoff, mask, val);
1098 #else
1099 ASSERT(0);
1100 return 0;
1101 #endif
1105 void si_core_disable(si_t *sih, uint32 bits)
1108 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1109 ai_core_disable(sih, bits);
1110 #ifdef BCMSDIO
1111 else
1112 sb_core_disable(sih, bits);
1113 #endif
1116 void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1118 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1119 ai_core_reset(sih, bits, resetbits);
1120 #ifdef BCMSDIO
1121 else
1122 sb_core_reset(sih, bits, resetbits);
1123 #endif
1126 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1127 int si_corebist(si_t *sih)
1129 uint32 cflags;
1130 int result = 0;
1132 /* Read core control flags */
1133 cflags = si_core_cflags(sih, 0, 0);
1135 /* Set bist & fgc */
1136 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1138 /* Wait for bist done */
1139 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1141 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1142 result = BCME_ERROR;
1144 /* Reset core control flags */
1145 si_core_cflags(sih, 0xffff, cflags);
1147 return result;
1150 static uint32 BCMINITFN(factor6) (uint32 x)
1152 switch (x) {
1153 case CC_F6_2:
1154 return 2;
1155 case CC_F6_3:
1156 return 3;
1157 case CC_F6_4:
1158 return 4;
1159 case CC_F6_5:
1160 return 5;
1161 case CC_F6_6:
1162 return 6;
1163 case CC_F6_7:
1164 return 7;
1165 default:
1166 return 0;
1170 /* calculate the speed the SI would run at given a set of clockcontrol values */
1171 uint32 BCMINITFN(si_clock_rate) (uint32 pll_type, uint32 n, uint32 m)
1173 uint32 n1, n2, clock, m1, m2, m3, mc;
1175 n1 = n & CN_N1_MASK;
1176 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1178 if (pll_type == PLL_TYPE6) {
1179 if (m & CC_T6_MMASK)
1180 return CC_T6_M1;
1181 else
1182 return CC_T6_M0;
1183 } else if ((pll_type == PLL_TYPE1) ||
1184 (pll_type == PLL_TYPE3) ||
1185 (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1186 n1 = factor6(n1);
1187 n2 += CC_F5_BIAS;
1188 } else if (pll_type == PLL_TYPE2) {
1189 n1 += CC_T2_BIAS;
1190 n2 += CC_T2_BIAS;
1191 ASSERT((n1 >= 2) && (n1 <= 7));
1192 ASSERT((n2 >= 5) && (n2 <= 23));
1193 } else if (pll_type == PLL_TYPE5) {
1194 return 100000000;
1195 } else
1196 ASSERT(0);
1197 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1198 if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) {
1199 clock = CC_CLOCK_BASE2 * n1 * n2;
1200 } else
1201 clock = CC_CLOCK_BASE1 * n1 * n2;
1203 if (clock == 0)
1204 return 0;
1206 m1 = m & CC_M1_MASK;
1207 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1208 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1209 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1211 if ((pll_type == PLL_TYPE1) ||
1212 (pll_type == PLL_TYPE3) ||
1213 (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1214 m1 = factor6(m1);
1215 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1216 m2 += CC_F5_BIAS;
1217 else
1218 m2 = factor6(m2);
1219 m3 = factor6(m3);
1221 switch (mc) {
1222 case CC_MC_BYPASS:
1223 return clock;
1224 case CC_MC_M1:
1225 return clock / m1;
1226 case CC_MC_M1M2:
1227 return clock / (m1 * m2);
1228 case CC_MC_M1M2M3:
1229 return clock / (m1 * m2 * m3);
1230 case CC_MC_M1M3:
1231 return clock / (m1 * m3);
1232 default:
1233 return 0;
1235 } else {
1236 ASSERT(pll_type == PLL_TYPE2);
1238 m1 += CC_T2_BIAS;
1239 m2 += CC_T2M2_BIAS;
1240 m3 += CC_T2_BIAS;
1241 ASSERT((m1 >= 2) && (m1 <= 7));
1242 ASSERT((m2 >= 3) && (m2 <= 10));
1243 ASSERT((m3 >= 2) && (m3 <= 7));
1245 if ((mc & CC_T2MC_M1BYP) == 0)
1246 clock /= m1;
1247 if ((mc & CC_T2MC_M2BYP) == 0)
1248 clock /= m2;
1249 if ((mc & CC_T2MC_M3BYP) == 0)
1250 clock /= m3;
1252 return clock;
1256 uint32 BCMINITFN(si_clock) (si_t *sih)
1258 si_info_t *sii;
1259 chipcregs_t *cc;
1260 uint32 n, m;
1261 uint idx;
1262 uint32 pll_type, rate;
1263 uint intr_val = 0;
1265 sii = SI_INFO(sih);
1266 INTR_OFF(sii, intr_val);
1267 if (PMUCTL_ENAB(sih)) {
1268 rate = si_pmu_si_clock(sih, sii->osh);
1269 goto exit;
1272 idx = sii->curidx;
1273 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1274 ASSERT(cc != NULL);
1276 n = R_REG(sii->osh, &cc->clockcontrol_n);
1277 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1278 if (pll_type == PLL_TYPE6)
1279 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1280 else if (pll_type == PLL_TYPE3)
1281 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1282 else
1283 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1285 /* calculate rate */
1286 rate = si_clock_rate(pll_type, n, m);
1288 if (pll_type == PLL_TYPE3)
1289 rate = rate / 2;
1291 /* switch back to previous core */
1292 si_setcoreidx(sih, idx);
1293 exit:
1294 INTR_RESTORE(sii, intr_val);
1296 return rate;
1299 uint32 BCMINITFN(si_alp_clock) (si_t *sih)
1301 if (PMUCTL_ENAB(sih))
1302 return si_pmu_alp_clock(sih, si_osh(sih));
1304 return ALP_CLOCK;
1307 uint32 BCMINITFN(si_ilp_clock) (si_t *sih)
1309 if (PMUCTL_ENAB(sih))
1310 return si_pmu_ilp_clock(sih, si_osh(sih));
1312 return ILP_CLOCK;
1315 /* set chip watchdog reset timer to fire in 'ticks' */
1316 #ifdef BRCM_FULLMAC
1317 void
1318 si_watchdog(si_t *sih, uint ticks)
1320 if (PMUCTL_ENAB(sih)) {
1322 if ((sih->chip == BCM4319_CHIP_ID) && (sih->chiprev == 0) &&
1323 (ticks != 0)) {
1324 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t,
1325 clk_ctl_st), ~0, 0x2);
1326 si_setcore(sih, USB20D_CORE_ID, 0);
1327 si_core_disable(sih, 1);
1328 si_setcore(sih, CC_CORE_ID, 0);
1331 if (ticks == 1)
1332 ticks = 2;
1333 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog),
1334 ~0, ticks);
1335 } else {
1336 /* instant NMI */
1337 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog),
1338 ~0, ticks);
1341 #else
1342 void si_watchdog(si_t *sih, uint ticks)
1344 uint nb, maxt;
1346 if (PMUCTL_ENAB(sih)) {
1348 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1349 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1350 si_corereg(sih, SI_CC_IDX,
1351 OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1352 si_setcore(sih, USB20D_CORE_ID, 0);
1353 si_core_disable(sih, 1);
1354 si_setcore(sih, CC_CORE_ID, 0);
1357 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1358 /* The mips compiler uses the sllv instruction,
1359 * so we specially handle the 32-bit case.
1361 if (nb == 32)
1362 maxt = 0xffffffff;
1363 else
1364 maxt = ((1 << nb) - 1);
1366 if (ticks == 1)
1367 ticks = 2;
1368 else if (ticks > maxt)
1369 ticks = maxt;
1371 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog),
1372 ~0, ticks);
1373 } else {
1374 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1375 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1376 maxt = (1 << 28) - 1;
1377 if (ticks > maxt)
1378 ticks = maxt;
1380 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
1381 ticks);
1384 #endif
1386 /* trigger watchdog reset after ms milliseconds */
1387 void si_watchdog_ms(si_t *sih, uint32 ms)
1389 si_watchdog(sih, wd_msticks * ms);
1392 uint16 BCMATTACHFN(si_d11_devid) (si_t *sih)
1394 si_info_t *sii = SI_INFO(sih);
1395 uint16 device;
1397 /* normal case: nvram variable with devpath->devid->wl0id */
1398 device = (uint16) si_getdevpathintvar(sih, "devid");
1399 if (device != 0)
1400 goto bail;
1402 /* Get devid from OTP/SPROM depending on where the SROM is read */
1403 device = (uint16) getintvar(sii->vars, "devid");
1404 if (device != 0)
1405 goto bail;
1407 /* no longer support wl0id, but keep the code here for backward compatibility. */
1408 device = (uint16) getintvar(sii->vars, "wl0id");
1409 if (device != 0)
1410 goto bail;
1412 /* ignore it */
1413 device = 0xffff;
1415 bail:
1416 return device;
1419 /* return the slow clock source - LPO, XTAL, or PCI */
1420 static uint si_slowclk_src(si_info_t *sii)
1422 chipcregs_t *cc;
1424 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1426 if (sii->pub.ccrev < 6) {
1427 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1428 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32))
1429 & PCI_CFG_GPIO_SCS))
1430 return SCC_SS_PCI;
1431 else
1432 return SCC_SS_XTAL;
1433 } else if (sii->pub.ccrev < 10) {
1434 cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
1435 return R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK;
1436 } else /* Insta-clock */
1437 return SCC_SS_XTAL;
1440 /* return the ILP (slowclock) min or max frequency */
1441 static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1443 uint32 slowclk;
1444 uint div;
1446 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1448 /* shouldn't be here unless we've established the chip has dynamic clk control */
1449 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1451 slowclk = si_slowclk_src(sii);
1452 if (sii->pub.ccrev < 6) {
1453 if (slowclk == SCC_SS_PCI)
1454 return max_freq ? (PCIMAXFREQ / 64)
1455 : (PCIMINFREQ / 64);
1456 else
1457 return max_freq ? (XTALMAXFREQ / 32)
1458 : (XTALMINFREQ / 32);
1459 } else if (sii->pub.ccrev < 10) {
1460 div = 4 *
1461 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
1462 SCC_CD_SHIFT) + 1);
1463 if (slowclk == SCC_SS_LPO)
1464 return max_freq ? LPOMAXFREQ : LPOMINFREQ;
1465 else if (slowclk == SCC_SS_XTAL)
1466 return max_freq ? (XTALMAXFREQ / div)
1467 : (XTALMINFREQ / div);
1468 else if (slowclk == SCC_SS_PCI)
1469 return max_freq ? (PCIMAXFREQ / div)
1470 : (PCIMINFREQ / div);
1471 else
1472 ASSERT(0);
1473 } else {
1474 /* Chipc rev 10 is InstaClock */
1475 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1476 div = 4 * (div + 1);
1477 return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
1479 return 0;
1482 static void BCMINITFN(si_clkctl_setdelay) (si_info_t *sii, void *chipcregs)
1484 chipcregs_t *cc = (chipcregs_t *) chipcregs;
1485 uint slowmaxfreq, pll_delay, slowclk;
1486 uint pll_on_delay, fref_sel_delay;
1488 pll_delay = PLL_DELAY;
1490 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1491 * since the xtal will also be powered down by dynamic clk control logic.
1494 slowclk = si_slowclk_src(sii);
1495 if (slowclk != SCC_SS_XTAL)
1496 pll_delay += XTAL_ON_DELAY;
1498 /* Starting with 4318 it is ILP that is used for the delays */
1499 slowmaxfreq =
1500 si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1502 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1503 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1505 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1506 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1509 /* initialize power control delay registers */
1510 void BCMINITFN(si_clkctl_init) (si_t *sih)
1512 si_info_t *sii;
1513 uint origidx = 0;
1514 chipcregs_t *cc;
1515 bool fast;
1517 if (!CCCTL_ENAB(sih))
1518 return;
1520 sii = SI_INFO(sih);
1521 fast = SI_FAST(sii);
1522 if (!fast) {
1523 origidx = sii->curidx;
1524 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1525 if (cc == NULL)
1526 return;
1527 } else {
1528 cc = (chipcregs_t *) CCREGS_FAST(sii);
1529 if (cc == NULL)
1530 return;
1532 ASSERT(cc != NULL);
1534 /* set all Instaclk chip ILP to 1 MHz */
1535 if (sih->ccrev >= 10)
1536 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1537 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1539 si_clkctl_setdelay(sii, (void *)(uintptr) cc);
1541 if (!fast)
1542 si_setcoreidx(sih, origidx);
1545 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1546 uint16 BCMINITFN(si_clkctl_fast_pwrup_delay) (si_t *sih)
1548 si_info_t *sii;
1549 uint origidx = 0;
1550 chipcregs_t *cc;
1551 uint slowminfreq;
1552 uint16 fpdelay;
1553 uint intr_val = 0;
1554 bool fast;
1556 sii = SI_INFO(sih);
1557 if (PMUCTL_ENAB(sih)) {
1558 INTR_OFF(sii, intr_val);
1559 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1560 INTR_RESTORE(sii, intr_val);
1561 return fpdelay;
1564 if (!CCCTL_ENAB(sih))
1565 return 0;
1567 fast = SI_FAST(sii);
1568 fpdelay = 0;
1569 if (!fast) {
1570 origidx = sii->curidx;
1571 INTR_OFF(sii, intr_val);
1572 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1573 if (cc == NULL)
1574 goto done;
1575 } else {
1576 cc = (chipcregs_t *) CCREGS_FAST(sii);
1577 if (cc == NULL)
1578 goto done;
1580 ASSERT(cc != NULL);
1582 slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1583 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1584 (slowminfreq - 1)) / slowminfreq;
1586 done:
1587 if (!fast) {
1588 si_setcoreidx(sih, origidx);
1589 INTR_RESTORE(sii, intr_val);
1591 return fpdelay;
1594 /* turn primary xtal and/or pll off/on */
1595 int si_clkctl_xtal(si_t *sih, uint what, bool on)
1597 si_info_t *sii;
1598 uint32 in, out, outen;
1600 sii = SI_INFO(sih);
1602 switch (BUSTYPE(sih->bustype)) {
1604 #ifdef BCMSDIO
1605 case SDIO_BUS:
1606 return -1;
1607 #endif /* BCMSDIO */
1609 case PCI_BUS:
1610 /* pcie core doesn't have any mapping to control the xtal pu */
1611 if (PCIE(sii))
1612 return -1;
1614 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
1615 out =
1616 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
1617 outen =
1618 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1619 sizeof(uint32));
1622 * Avoid glitching the clock if GPRS is already using it.
1623 * We can't actually read the state of the PLLPD so we infer it
1624 * by the value of XTAL_PU which *is* readable via gpioin.
1626 if (on && (in & PCI_CFG_GPIO_XTAL))
1627 return 0;
1629 if (what & XTAL)
1630 outen |= PCI_CFG_GPIO_XTAL;
1631 if (what & PLL)
1632 outen |= PCI_CFG_GPIO_PLL;
1634 if (on) {
1635 /* turn primary xtal on */
1636 if (what & XTAL) {
1637 out |= PCI_CFG_GPIO_XTAL;
1638 if (what & PLL)
1639 out |= PCI_CFG_GPIO_PLL;
1640 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1641 sizeof(uint32), out);
1642 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1643 sizeof(uint32), outen);
1644 OSL_DELAY(XTAL_ON_DELAY);
1647 /* turn pll on */
1648 if (what & PLL) {
1649 out &= ~PCI_CFG_GPIO_PLL;
1650 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1651 sizeof(uint32), out);
1652 OSL_DELAY(2000);
1654 } else {
1655 if (what & XTAL)
1656 out &= ~PCI_CFG_GPIO_XTAL;
1657 if (what & PLL)
1658 out |= PCI_CFG_GPIO_PLL;
1659 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1660 sizeof(uint32), out);
1661 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1662 sizeof(uint32), outen);
1665 default:
1666 return -1;
1669 return 0;
1673 * clock control policy function throught chipcommon
1675 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1676 * returns true if we are forcing fast clock
1677 * this is a wrapper over the next internal function
1678 * to allow flexible policy settings for outside caller
1680 bool si_clkctl_cc(si_t *sih, uint mode)
1682 si_info_t *sii;
1684 sii = SI_INFO(sih);
1686 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1687 if (sih->ccrev < 6)
1688 return FALSE;
1690 if (PCI_FORCEHT(sii))
1691 return mode == CLK_FAST;
1693 return _si_clkctl_cc(sii, mode);
1696 /* clk control mechanism through chipcommon, no policy checking */
1697 static bool _si_clkctl_cc(si_info_t *sii, uint mode)
1699 uint origidx = 0;
1700 chipcregs_t *cc;
1701 uint32 scc;
1702 uint intr_val = 0;
1703 bool fast = SI_FAST(sii);
1705 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1706 if (sii->pub.ccrev < 6)
1707 return FALSE;
1709 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1710 ASSERT(sii->pub.ccrev != 10);
1712 if (!fast) {
1713 INTR_OFF(sii, intr_val);
1714 origidx = sii->curidx;
1716 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1717 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1718 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1719 goto done;
1721 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
1722 } else {
1723 cc = (chipcregs_t *) CCREGS_FAST(sii);
1724 if (cc == NULL)
1725 goto done;
1727 ASSERT(cc != NULL);
1729 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1730 goto done;
1732 switch (mode) {
1733 case CLK_FAST: /* FORCEHT, fast (pll) clock */
1734 if (sii->pub.ccrev < 10) {
1735 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1736 si_clkctl_xtal(&sii->pub, XTAL, ON);
1737 SET_REG(sii->osh, &cc->slow_clk_ctl,
1738 (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1739 } else if (sii->pub.ccrev < 20) {
1740 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1741 } else {
1742 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1745 /* wait for the PLL */
1746 if (PMUCTL_ENAB(&sii->pub)) {
1747 uint32 htavail = CCS_HTAVAIL;
1748 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
1749 == 0), PMU_MAX_TRANSITION_DLY);
1750 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1751 } else {
1752 OSL_DELAY(PLL_DELAY);
1754 break;
1756 case CLK_DYNAMIC: /* enable dynamic clock control */
1757 if (sii->pub.ccrev < 10) {
1758 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1759 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
1760 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
1761 scc |= SCC_XC;
1762 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
1764 /* for dynamic control, we have to release our xtal_pu "force on" */
1765 if (scc & SCC_XC)
1766 si_clkctl_xtal(&sii->pub, XTAL, OFF);
1767 } else if (sii->pub.ccrev < 20) {
1768 /* Instaclock */
1769 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
1770 } else {
1771 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
1773 break;
1775 default:
1776 ASSERT(0);
1779 done:
1780 if (!fast) {
1781 si_setcoreidx(&sii->pub, origidx);
1782 INTR_RESTORE(sii, intr_val);
1784 return mode == CLK_FAST;
1787 /* Build device path. Support SI, PCI, and JTAG for now. */
1788 int BCMATTACHFN(si_devpath) (si_t *sih, char *path, int size)
1790 int slen;
1792 ASSERT(path != NULL);
1793 ASSERT(size >= SI_DEVPATH_BUFSZ);
1795 if (!path || size <= 0)
1796 return -1;
1798 switch (BUSTYPE(sih->bustype)) {
1799 case SI_BUS:
1800 case JTAG_BUS:
1801 slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
1802 break;
1803 case PCI_BUS:
1804 ASSERT((SI_INFO(sih))->osh != NULL);
1805 slen = snprintf(path, (size_t) size, "pci/%u/%u/",
1806 OSL_PCI_BUS((SI_INFO(sih))->osh),
1807 OSL_PCI_SLOT((SI_INFO(sih))->osh));
1808 break;
1810 #ifdef BCMSDIO
1811 case SDIO_BUS:
1812 SI_ERROR(("si_devpath: device 0 assumed\n"));
1813 slen = snprintf(path, (size_t) size, "sd/%u/", si_coreidx(sih));
1814 break;
1815 #endif
1816 default:
1817 slen = -1;
1818 ASSERT(0);
1819 break;
1822 if (slen < 0 || slen >= size) {
1823 path[0] = '\0';
1824 return -1;
1827 return 0;
1830 /* Get a variable, but only if it has a devpath prefix */
1831 char *BCMATTACHFN(si_getdevpathvar) (si_t *sih, const char *name)
1833 char varname[SI_DEVPATH_BUFSZ + 32];
1835 si_devpathvar(sih, varname, sizeof(varname), name);
1837 return getvar(NULL, varname);
1840 /* Get a variable, but only if it has a devpath prefix */
1841 int BCMATTACHFN(si_getdevpathintvar) (si_t *sih, const char *name)
1843 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1844 return getintvar(NULL, name);
1845 #else
1846 char varname[SI_DEVPATH_BUFSZ + 32];
1848 si_devpathvar(sih, varname, sizeof(varname), name);
1850 return getintvar(NULL, varname);
1851 #endif
1854 char *si_getnvramflvar(si_t *sih, const char *name)
1856 return getvar(NULL, name);
1859 /* Concatenate the dev path with a varname into the given 'var' buffer
1860 * and return the 'var' pointer.
1861 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1862 * On overflow, the first char will be set to '\0'.
1864 static char *BCMATTACHFN(si_devpathvar) (si_t *sih, char *var, int len,
1865 const char *name) {
1866 uint path_len;
1868 if (!var || len <= 0)
1869 return var;
1871 if (si_devpath(sih, var, len) == 0) {
1872 path_len = strlen(var);
1874 if (strlen(name) + 1 > (uint) (len - path_len))
1875 var[0] = '\0';
1876 else
1877 strncpy(var + path_len, name, len - path_len - 1);
1880 return var;
1883 uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
1885 si_info_t *sii;
1887 sii = SI_INFO(sih);
1889 if (!PCIE(sii)) {
1890 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1891 return 0;
1894 return pcicore_pciereg(sii->pch, offset, mask, val, type);
1897 uint32
1898 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask,
1899 uint32 val)
1901 si_info_t *sii;
1903 sii = SI_INFO(sih);
1905 if (!PCIE(sii)) {
1906 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1907 return 0;
1910 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
1914 /* return TRUE if PCIE capability exists in the pci config space */
1915 static __used bool si_ispcie(si_info_t *sii)
1917 u8 cap_ptr;
1919 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1920 return FALSE;
1922 cap_ptr =
1923 pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1924 NULL);
1925 if (!cap_ptr)
1926 return FALSE;
1928 return TRUE;
1931 /* Wake-on-wireless-LAN (WOWL) support functions */
1932 /* Enable PME generation and disable clkreq */
1933 void si_pci_pmeen(si_t *sih)
1935 si_info_t *sii;
1937 sii = SI_INFO(sih);
1939 pcicore_pmeen(sii->pch);
1942 /* Return TRUE if PME status is set */
1943 bool si_pci_pmestat(si_t *sih)
1945 si_info_t *sii;
1947 sii = SI_INFO(sih);
1949 return pcicore_pmestat(sii->pch);
1952 /* Disable PME generation, clear the PME status bit if set */
1953 void si_pci_pmeclr(si_t *sih)
1955 si_info_t *sii;
1957 sii = SI_INFO(sih);
1959 pcicore_pmeclr(sii->pch);
1962 #ifdef BCMSDIO
1963 /* initialize the sdio core */
1964 void si_sdio_init(si_t *sih)
1966 si_info_t *sii = SI_INFO(sih);
1968 if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1969 (sih->buscoretype == SDIOD_CORE_ID)) {
1970 uint idx;
1971 sdpcmd_regs_t *sdpregs;
1973 /* get the current core index */
1974 idx = sii->curidx;
1975 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1977 /* switch to sdio core */
1978 sdpregs = (sdpcmd_regs_t *) si_setcore(sih, PCMCIA_CORE_ID, 0);
1979 if (!sdpregs)
1980 sdpregs =
1981 (sdpcmd_regs_t *) si_setcore(sih, SDIOD_CORE_ID, 0);
1982 ASSERT(sdpregs);
1984 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));
1986 /* enable backplane error and core interrupts */
1987 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
1988 W_REG(sii->osh, &sdpregs->sbintmask,
1989 (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
1991 /* switch back to previous core */
1992 si_setcoreidx(sih, idx);
1995 /* enable interrupts */
1996 bcmsdh_intr_enable(sii->sdh);
1999 #endif /* BCMSDIO */
2001 bool BCMATTACHFN(si_pci_war16165) (si_t *sih)
2003 si_info_t *sii;
2005 sii = SI_INFO(sih);
2007 return PCI(sii) && (sih->buscorerev <= 10);
2010 /* Disable pcie_war_ovr for some platforms (sigh!)
2011 * This is for boards that have BFL2_PCIEWAR_OVR set
2012 * but are in systems that still want the benefits of ASPM
2013 * Note that this should be done AFTER si_doattach
2015 void si_pcie_war_ovr_update(si_t *sih, u8 aspm)
2017 si_info_t *sii;
2019 sii = SI_INFO(sih);
2021 if (!PCIE(sii))
2022 return;
2024 pcie_war_ovr_aspm_update(sii->pch, aspm);
2027 /* back door for other module to override chippkg */
2028 void si_chippkg_set(si_t *sih, uint val)
2030 si_info_t *sii;
2032 sii = SI_INFO(sih);
2034 sii->pub.chippkg = val;
2037 void BCMINITFN(si_pci_up) (si_t *sih)
2039 si_info_t *sii;
2041 sii = SI_INFO(sih);
2043 /* if not pci bus, we're done */
2044 if (BUSTYPE(sih->bustype) != PCI_BUS)
2045 return;
2047 if (PCI_FORCEHT(sii))
2048 _si_clkctl_cc(sii, CLK_FAST);
2050 if (PCIE(sii))
2051 pcicore_up(sii->pch, SI_PCIUP);
2055 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2056 void BCMUNINITFN(si_pci_sleep) (si_t *sih)
2058 si_info_t *sii;
2060 sii = SI_INFO(sih);
2062 pcicore_sleep(sii->pch);
2065 /* Unconfigure and/or apply various WARs when going down */
2066 void BCMINITFN(si_pci_down) (si_t *sih)
2068 si_info_t *sii;
2070 sii = SI_INFO(sih);
2072 /* if not pci bus, we're done */
2073 if (BUSTYPE(sih->bustype) != PCI_BUS)
2074 return;
2076 /* release FORCEHT since chip is going to "down" state */
2077 if (PCI_FORCEHT(sii))
2078 _si_clkctl_cc(sii, CLK_DYNAMIC);
2080 pcicore_down(sii->pch, SI_PCIDOWN);
2084 * Configure the pci core for pci client (NIC) action
2085 * coremask is the bitvec of cores by index to be enabled.
2087 void BCMATTACHFN(si_pci_setup) (si_t *sih, uint coremask)
2089 si_info_t *sii;
2090 sbpciregs_t *pciregs = NULL;
2091 uint32 siflag = 0, w;
2092 uint idx = 0;
2094 sii = SI_INFO(sih);
2096 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2097 return;
2099 ASSERT(PCI(sii) || PCIE(sii));
2100 ASSERT(sii->pub.buscoreidx != BADIDX);
2102 if (PCI(sii)) {
2103 /* get current core index */
2104 idx = sii->curidx;
2106 /* we interrupt on this backplane flag number */
2107 siflag = si_flag(sih);
2109 /* switch over to pci core */
2110 pciregs =
2111 (sbpciregs_t *) si_setcoreidx(sih, sii->pub.buscoreidx);
2115 * Enable sb->pci interrupts. Assume
2116 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2118 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2119 /* pci config write to set this core bit in PCIIntMask */
2120 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2121 w |= (coremask << PCI_SBIM_SHIFT);
2122 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2123 } else {
2124 /* set sbintvec bit for our flag number */
2125 si_setint(sih, siflag);
2128 if (PCI(sii)) {
2129 OR_REG(sii->osh, &pciregs->sbtopci2,
2130 (SBTOPCI_PREF | SBTOPCI_BURST));
2131 if (sii->pub.buscorerev >= 11) {
2132 OR_REG(sii->osh, &pciregs->sbtopci2,
2133 SBTOPCI_RC_READMULTI);
2134 w = R_REG(sii->osh, &pciregs->clkrun);
2135 W_REG(sii->osh, &pciregs->clkrun,
2136 (w | PCI_CLKRUN_DSBL));
2137 w = R_REG(sii->osh, &pciregs->clkrun);
2140 /* switch back to previous core */
2141 si_setcoreidx(sih, idx);
2145 u8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2147 si_info_t *sii;
2149 sii = SI_INFO(sih);
2151 if (!(PCIE(sii)))
2152 return 0;
2153 return pcie_clkreq(sii->pch, mask, val);
2156 uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2158 si_info_t *sii;
2160 sii = SI_INFO(sih);
2162 if (!PCIE(sii))
2163 return 0;
2165 return pcie_lcreg(sii->pch, mask, val);
2168 /* indirect way to read pcie config regs */
2169 uint si_pcie_readreg(void *sih, uint addrtype, uint offset)
2171 return pcie_readreg(((si_info_t *) sih)->osh,
2172 (sbpcieregs_t *) PCIEREGS(((si_info_t *) sih)),
2173 addrtype, offset);
2177 * Fixup SROMless PCI device's configuration.
2178 * The current core may be changed upon return.
2180 int si_pci_fixcfg(si_t *sih)
2182 uint origidx, pciidx;
2183 sbpciregs_t *pciregs = NULL;
2184 sbpcieregs_t *pcieregs = NULL;
2185 void *regs = NULL;
2186 uint16 val16, *reg16 = NULL;
2188 si_info_t *sii = SI_INFO(sih);
2190 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2192 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2193 /* save the current index */
2194 origidx = si_coreidx(&sii->pub);
2196 /* check 'pi' is correct and fix it if not */
2197 if (sii->pub.buscoretype == PCIE_CORE_ID) {
2198 pcieregs =
2199 (sbpcieregs_t *) si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2200 regs = pcieregs;
2201 ASSERT(pcieregs != NULL);
2202 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2203 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
2204 pciregs = (sbpciregs_t *) si_setcore(&sii->pub, PCI_CORE_ID, 0);
2205 regs = pciregs;
2206 ASSERT(pciregs != NULL);
2207 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2209 pciidx = si_coreidx(&sii->pub);
2210 val16 = R_REG(sii->osh, reg16);
2211 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) {
2212 val16 =
2213 (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 &
2214 ~SRSH_PI_MASK);
2215 W_REG(sii->osh, reg16, val16);
2218 /* restore the original index */
2219 si_setcoreidx(&sii->pub, origidx);
2221 pcicore_hwup(sii->pch);
2222 return 0;
2225 /* change logical "focus" to the gpio core for optimized access */
2226 void *si_gpiosetcore(si_t *sih)
2228 return si_setcoreidx(sih, SI_CC_IDX);
2231 /* mask&set gpiocontrol bits */
2232 uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, u8 priority)
2234 uint regoff;
2236 regoff = 0;
2238 /* gpios could be shared on router platforms
2239 * ignore reservation if it's high priority (e.g., test apps)
2241 if ((priority != GPIO_HI_PRIORITY) &&
2242 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2243 mask = priority ? (si_gpioreservation & mask) :
2244 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2245 val &= mask;
2248 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2249 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2252 /* mask&set gpio output enable bits */
2253 uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, u8 priority)
2255 uint regoff;
2257 regoff = 0;
2259 /* gpios could be shared on router platforms
2260 * ignore reservation if it's high priority (e.g., test apps)
2262 if ((priority != GPIO_HI_PRIORITY) &&
2263 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2264 mask = priority ? (si_gpioreservation & mask) :
2265 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2266 val &= mask;
2269 regoff = OFFSETOF(chipcregs_t, gpioouten);
2270 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2273 /* mask&set gpio output bits */
2274 uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, u8 priority)
2276 uint regoff;
2278 regoff = 0;
2280 /* gpios could be shared on router platforms
2281 * ignore reservation if it's high priority (e.g., test apps)
2283 if ((priority != GPIO_HI_PRIORITY) &&
2284 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2285 mask = priority ? (si_gpioreservation & mask) :
2286 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2287 val &= mask;
2290 regoff = OFFSETOF(chipcregs_t, gpioout);
2291 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2294 /* reserve one gpio */
2295 uint32 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, u8 priority)
2297 si_info_t *sii;
2299 sii = SI_INFO(sih);
2301 /* only cores on SI_BUS share GPIO's and only applcation users need to
2302 * reserve/release GPIO
2304 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2305 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2306 return 0xffffffff;
2308 /* make sure only one bit is set */
2309 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2310 ASSERT((gpio_bitmask)
2311 && !((gpio_bitmask) & (gpio_bitmask - 1)));
2312 return 0xffffffff;
2315 /* already reserved */
2316 if (si_gpioreservation & gpio_bitmask)
2317 return 0xffffffff;
2318 /* set reservation */
2319 si_gpioreservation |= gpio_bitmask;
2321 return si_gpioreservation;
2324 /* release one gpio */
2326 * releasing the gpio doesn't change the current value on the GPIO last write value
2327 * persists till some one overwrites it
2330 uint32 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, u8 priority)
2332 si_info_t *sii;
2334 sii = SI_INFO(sih);
2336 /* only cores on SI_BUS share GPIO's and only applcation users need to
2337 * reserve/release GPIO
2339 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2340 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2341 return 0xffffffff;
2343 /* make sure only one bit is set */
2344 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2345 ASSERT((gpio_bitmask)
2346 && !((gpio_bitmask) & (gpio_bitmask - 1)));
2347 return 0xffffffff;
2350 /* already released */
2351 if (!(si_gpioreservation & gpio_bitmask))
2352 return 0xffffffff;
2354 /* clear reservation */
2355 si_gpioreservation &= ~gpio_bitmask;
2357 return si_gpioreservation;
2360 /* return the current gpioin register value */
2361 uint32 si_gpioin(si_t *sih)
2363 si_info_t *sii;
2364 uint regoff;
2366 sii = SI_INFO(sih);
2367 regoff = 0;
2369 regoff = OFFSETOF(chipcregs_t, gpioin);
2370 return si_corereg(sih, SI_CC_IDX, regoff, 0, 0);
2373 /* mask&set gpio interrupt polarity bits */
2374 uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, u8 priority)
2376 si_info_t *sii;
2377 uint regoff;
2379 sii = SI_INFO(sih);
2380 regoff = 0;
2382 /* gpios could be shared on router platforms */
2383 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2384 mask = priority ? (si_gpioreservation & mask) :
2385 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2386 val &= mask;
2389 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2390 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2393 /* mask&set gpio interrupt mask bits */
2394 uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, u8 priority)
2396 si_info_t *sii;
2397 uint regoff;
2399 sii = SI_INFO(sih);
2400 regoff = 0;
2402 /* gpios could be shared on router platforms */
2403 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2404 mask = priority ? (si_gpioreservation & mask) :
2405 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2406 val &= mask;
2409 regoff = OFFSETOF(chipcregs_t, gpiointmask);
2410 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2413 /* assign the gpio to an led */
2414 uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val)
2416 si_info_t *sii;
2418 sii = SI_INFO(sih);
2419 if (sih->ccrev < 16)
2420 return 0xffffffff;
2422 /* gpio led powersave reg */
2423 return si_corereg
2424 (sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
2425 val);
2428 /* mask&set gpio timer val */
2429 uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2431 si_info_t *sii;
2433 sii = SI_INFO(sih);
2435 if (sih->ccrev < 16)
2436 return 0xffffffff;
2438 return si_corereg(sih, SI_CC_IDX,
2439 OFFSETOF(chipcregs_t, gpiotimerval), mask,
2440 gpiotimerval);
2443 uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2445 si_info_t *sii;
2446 uint offs;
2448 sii = SI_INFO(sih);
2449 if (sih->ccrev < 20)
2450 return 0xffffffff;
2452 offs =
2453 (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
2454 OFFSETOF(chipcregs_t, gpiopullup));
2455 return si_corereg(sih, SI_CC_IDX, offs, mask, val);
2458 uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2460 si_info_t *sii;
2461 uint offs;
2463 sii = SI_INFO(sih);
2464 if (sih->ccrev < 11)
2465 return 0xffffffff;
2467 if (regtype == GPIO_REGEVT)
2468 offs = OFFSETOF(chipcregs_t, gpioevent);
2469 else if (regtype == GPIO_REGEVT_INTMSK)
2470 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2471 else if (regtype == GPIO_REGEVT_INTPOL)
2472 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2473 else
2474 return 0xffffffff;
2476 return si_corereg(sih, SI_CC_IDX, offs, mask, val);
2479 void *BCMATTACHFN(si_gpio_handler_register) (si_t *sih, uint32 event,
2480 bool level, gpio_handler_t cb,
2481 void *arg) {
2482 si_info_t *sii;
2483 gpioh_item_t *gi;
2485 ASSERT(event);
2486 ASSERT(cb != NULL);
2488 sii = SI_INFO(sih);
2489 if (sih->ccrev < 11)
2490 return NULL;
2492 gi = MALLOC(sii->osh, sizeof(gpioh_item_t));
2493 if (gi == NULL)
2494 return NULL;
2496 bzero(gi, sizeof(gpioh_item_t));
2497 gi->event = event;
2498 gi->handler = cb;
2499 gi->arg = arg;
2500 gi->level = level;
2502 gi->next = sii->gpioh_head;
2503 sii->gpioh_head = gi;
2505 return (void *)(gi);
2508 void BCMATTACHFN(si_gpio_handler_unregister) (si_t *sih, void *gpioh)
2510 si_info_t *sii;
2511 gpioh_item_t *p, *n;
2513 sii = SI_INFO(sih);
2514 if (sih->ccrev < 11)
2515 return;
2517 ASSERT(sii->gpioh_head != NULL);
2518 if ((void *)sii->gpioh_head == gpioh) {
2519 sii->gpioh_head = sii->gpioh_head->next;
2520 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2521 return;
2522 } else {
2523 p = sii->gpioh_head;
2524 n = p->next;
2525 while (n) {
2526 if ((void *)n == gpioh) {
2527 p->next = n->next;
2528 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2529 return;
2531 p = n;
2532 n = n->next;
2536 ASSERT(0); /* Not found in list */
2539 void si_gpio_handler_process(si_t *sih)
2541 si_info_t *sii;
2542 gpioh_item_t *h;
2543 uint32 status;
2544 uint32 level = si_gpioin(sih);
2545 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
2547 sii = SI_INFO(sih);
2548 for (h = sii->gpioh_head; h != NULL; h = h->next) {
2549 if (h->handler) {
2550 status = (h->level ? level : edge);
2552 if (status & h->event)
2553 h->handler(status, h->arg);
2557 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
2560 uint32 si_gpio_int_enable(si_t *sih, bool enable)
2562 si_info_t *sii;
2563 uint offs;
2565 sii = SI_INFO(sih);
2566 if (sih->ccrev < 11)
2567 return 0xffffffff;
2569 offs = OFFSETOF(chipcregs_t, intmask);
2570 return si_corereg
2571 (sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0));
2574 /* Return the size of the specified SOCRAM bank */
2575 static uint
2576 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, u8 index,
2577 u8 mem_type)
2579 uint banksize, bankinfo;
2580 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2582 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
2584 W_REG(sii->osh, &regs->bankidx, bankidx);
2585 bankinfo = R_REG(sii->osh, &regs->bankinfo);
2586 banksize =
2587 SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
2588 return banksize;
2591 void si_socdevram(si_t *sih, bool set, u8 *enable, u8 *protect)
2593 si_info_t *sii;
2594 uint origidx;
2595 uint intr_val = 0;
2596 sbsocramregs_t *regs;
2597 bool wasup;
2598 uint corerev;
2600 sii = SI_INFO(sih);
2602 /* Block ints and save current core */
2603 INTR_OFF(sii, intr_val);
2604 origidx = si_coreidx(sih);
2606 if (!set)
2607 *enable = *protect = 0;
2609 /* Switch to SOCRAM core */
2610 regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2611 if (!regs)
2612 goto done;
2614 /* Get info for determining size */
2615 wasup = si_iscoreup(sih);
2616 if (!wasup)
2617 si_core_reset(sih, 0, 0);
2619 corerev = si_corerev(sih);
2620 if (corerev >= 10) {
2621 uint32 extcinfo;
2622 u8 nb;
2623 u8 i;
2624 uint32 bankidx, bankinfo;
2626 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
2627 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2628 SOCRAM_DEVRAMBANK_SHIFT);
2629 for (i = 0; i < nb; i++) {
2630 bankidx =
2631 i | (SOCRAM_MEMTYPE_DEVRAM <<
2632 SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2633 W_REG(sii->osh, &regs->bankidx, bankidx);
2634 bankinfo = R_REG(sii->osh, &regs->bankinfo);
2635 if (set) {
2636 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
2637 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
2638 if (*enable) {
2639 bankinfo |=
2640 (1 <<
2641 SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
2642 if (*protect)
2643 bankinfo |=
2644 (1 <<
2645 SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
2647 W_REG(sii->osh, &regs->bankinfo, bankinfo);
2648 } else if (i == 0) {
2649 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
2650 *enable = 1;
2651 if (bankinfo &
2652 SOCRAM_BANKINFO_DEVRAMPRO_MASK)
2653 *protect = 1;
2659 /* Return to previous state and core */
2660 if (!wasup)
2661 si_core_disable(sih, 0);
2662 si_setcoreidx(sih, origidx);
2664 done:
2665 INTR_RESTORE(sii, intr_val);
2668 bool si_socdevram_pkg(si_t *sih)
2670 if (si_socdevram_size(sih) > 0)
2671 return TRUE;
2672 else
2673 return FALSE;
2676 uint32 si_socdevram_size(si_t *sih)
2678 si_info_t *sii;
2679 uint origidx;
2680 uint intr_val = 0;
2681 uint32 memsize = 0;
2682 sbsocramregs_t *regs;
2683 bool wasup;
2684 uint corerev;
2686 sii = SI_INFO(sih);
2688 /* Block ints and save current core */
2689 INTR_OFF(sii, intr_val);
2690 origidx = si_coreidx(sih);
2692 /* Switch to SOCRAM core */
2693 regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2694 if (!regs)
2695 goto done;
2697 /* Get info for determining size */
2698 wasup = si_iscoreup(sih);
2699 if (!wasup)
2700 si_core_reset(sih, 0, 0);
2702 corerev = si_corerev(sih);
2703 if (corerev >= 10) {
2704 uint32 extcinfo;
2705 u8 nb;
2706 u8 i;
2708 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
2709 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2710 SOCRAM_DEVRAMBANK_SHIFT));
2711 for (i = 0; i < nb; i++)
2712 memsize +=
2713 socram_banksize(sii, regs, i,
2714 SOCRAM_MEMTYPE_DEVRAM);
2717 /* Return to previous state and core */
2718 if (!wasup)
2719 si_core_disable(sih, 0);
2720 si_setcoreidx(sih, origidx);
2722 done:
2723 INTR_RESTORE(sii, intr_val);
2725 return memsize;
2728 /* Return the RAM size of the SOCRAM core */
2729 uint32 si_socram_size(si_t *sih)
2731 si_info_t *sii;
2732 uint origidx;
2733 uint intr_val = 0;
2735 sbsocramregs_t *regs;
2736 bool wasup;
2737 uint corerev;
2738 uint32 coreinfo;
2739 uint memsize = 0;
2741 sii = SI_INFO(sih);
2743 /* Block ints and save current core */
2744 INTR_OFF(sii, intr_val);
2745 origidx = si_coreidx(sih);
2747 /* Switch to SOCRAM core */
2748 regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2749 if (!regs)
2750 goto done;
2752 /* Get info for determining size */
2753 wasup = si_iscoreup(sih);
2754 if (!wasup)
2755 si_core_reset(sih, 0, 0);
2756 corerev = si_corerev(sih);
2757 coreinfo = R_REG(sii->osh, &regs->coreinfo);
2759 /* Calculate size from coreinfo based on rev */
2760 if (corerev == 0)
2761 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
2762 else if (corerev < 3) {
2763 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
2764 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2765 } else if ((corerev <= 7) || (corerev == 12)) {
2766 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2767 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
2768 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
2769 if (lss != 0)
2770 nb--;
2771 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
2772 if (lss != 0)
2773 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
2774 } else {
2775 u8 i;
2776 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2777 for (i = 0; i < nb; i++)
2778 memsize +=
2779 socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
2782 /* Return to previous state and core */
2783 if (!wasup)
2784 si_core_disable(sih, 0);
2785 si_setcoreidx(sih, origidx);
2787 done:
2788 INTR_RESTORE(sii, intr_val);
2790 return memsize;
2793 void si_chipcontrl_epa4331(si_t *sih, bool on)
2795 si_info_t *sii;
2796 chipcregs_t *cc;
2797 uint origidx;
2798 uint32 val;
2800 sii = SI_INFO(sih);
2801 origidx = si_coreidx(sih);
2803 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2805 val = R_REG(sii->osh, &cc->chipcontrol);
2807 if (on) {
2808 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
2809 /* Ext PA Controls for 4331 12x9 Package */
2810 W_REG(sii->osh, &cc->chipcontrol, val |
2811 (CCTRL4331_EXTPA_EN |
2812 CCTRL4331_EXTPA_ON_GPIO2_5));
2813 } else {
2814 /* Ext PA Controls for 4331 12x12 Package */
2815 W_REG(sii->osh, &cc->chipcontrol,
2816 val | (CCTRL4331_EXTPA_EN));
2818 } else {
2819 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2820 W_REG(sii->osh, &cc->chipcontrol, val);
2823 si_setcoreidx(sih, origidx);
2826 /* Enable BT-COEX & Ex-PA for 4313 */
2827 void si_epa_4313war(si_t *sih)
2829 si_info_t *sii;
2830 chipcregs_t *cc;
2831 uint origidx;
2833 sii = SI_INFO(sih);
2834 origidx = si_coreidx(sih);
2836 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2838 /* EPA Fix */
2839 W_REG(sii->osh, &cc->gpiocontrol,
2840 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2842 si_setcoreidx(sih, origidx);
2845 /* check if the device is removed */
2846 bool si_deviceremoved(si_t *sih)
2848 uint32 w;
2849 si_info_t *sii;
2851 sii = SI_INFO(sih);
2853 switch (BUSTYPE(sih->bustype)) {
2854 case PCI_BUS:
2855 ASSERT(sii->osh != NULL);
2856 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
2857 if ((w & 0xFFFF) != VENDOR_BROADCOM)
2858 return TRUE;
2859 break;
2861 return FALSE;
2864 bool si_is_sprom_available(si_t *sih)
2866 if (sih->ccrev >= 31) {
2867 si_info_t *sii;
2868 uint origidx;
2869 chipcregs_t *cc;
2870 uint32 sromctrl;
2872 if ((sih->cccaps & CC_CAP_SROM) == 0)
2873 return FALSE;
2875 sii = SI_INFO(sih);
2876 origidx = sii->curidx;
2877 cc = si_setcoreidx(sih, SI_CC_IDX);
2878 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
2879 si_setcoreidx(sih, origidx);
2880 return sromctrl & SRC_PRESENT;
2883 switch (CHIPID(sih->chip)) {
2884 case BCM4329_CHIP_ID:
2885 return (sih->chipst & CST4329_SPROM_SEL) != 0;
2886 case BCM4319_CHIP_ID:
2887 return (sih->chipst & CST4319_SPROM_SEL) != 0;
2888 case BCM4336_CHIP_ID:
2889 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
2890 case BCM4330_CHIP_ID:
2891 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
2892 case BCM4313_CHIP_ID:
2893 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
2894 case BCM4331_CHIP_ID:
2895 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
2896 default:
2897 return TRUE;
2901 bool si_is_otp_disabled(si_t *sih)
2903 switch (CHIPID(sih->chip)) {
2904 case BCM4329_CHIP_ID:
2905 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
2906 CST4329_OTP_PWRDN;
2907 case BCM4319_CHIP_ID:
2908 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
2909 CST4319_OTP_PWRDN;
2910 case BCM4336_CHIP_ID:
2911 return (sih->chipst & CST4336_OTP_PRESENT) == 0;
2912 case BCM4330_CHIP_ID:
2913 return (sih->chipst & CST4330_OTP_PRESENT) == 0;
2914 case BCM4313_CHIP_ID:
2915 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
2916 /* These chips always have their OTP on */
2917 case BCM43224_CHIP_ID:
2918 case BCM43225_CHIP_ID:
2919 case BCM43421_CHIP_ID:
2920 case BCM43235_CHIP_ID:
2921 case BCM43236_CHIP_ID:
2922 case BCM43238_CHIP_ID:
2923 case BCM4331_CHIP_ID:
2924 default:
2925 return FALSE;
2929 bool si_is_otp_powered(si_t *sih)
2931 if (PMUCTL_ENAB(sih))
2932 return si_pmu_is_otp_powered(sih, si_osh(sih));
2933 return TRUE;
2936 void si_otp_power(si_t *sih, bool on)
2938 if (PMUCTL_ENAB(sih))
2939 si_pmu_otp_power(sih, si_osh(sih), on);
2940 OSL_DELAY(1000);
2943 bool
2944 #if defined(BCMDBG)
2945 si_is_sprom_enabled(si_t *sih)
2946 #else
2947 BCMATTACHFN(si_is_sprom_enabled) (si_t *sih)
2948 #endif
2951 return TRUE;
2954 void
2955 #if defined(BCMDBG)
2956 si_sprom_enable(si_t *sih, bool enable)
2957 #else
2958 BCMATTACHFN(si_sprom_enable) (si_t *sih, bool enable)
2959 #endif
2961 if (PMUCTL_ENAB(sih))
2962 si_pmu_sprom_enable(sih, si_osh(sih), enable);
2965 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
2966 int si_cis_source(si_t *sih)
2968 /* Many chips have the same mapping of their chipstatus field */
2969 static const uint cis_sel[] = {
2970 CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
2971 static const uint cis_43236_sel[] = {
2972 CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_OTP };
2974 /* PCI chips use SROM format instead of CIS */
2975 if (BUSTYPE(sih->bustype) == PCI_BUS)
2976 return BCME_NOTFOUND;
2978 switch (CHIPID(sih->chip)) {
2979 case BCM43235_CHIP_ID:
2980 case BCM43236_CHIP_ID:
2981 case BCM43238_CHIP_ID:{
2982 u8 strap =
2983 (sih->
2984 chipst & CST4322_SPROM_OTP_SEL_MASK) >>
2985 CST4322_SPROM_OTP_SEL_SHIFT;
2986 return ((strap >=
2987 sizeof(cis_sel)) ? CIS_DEFAULT :
2988 cis_43236_sel[strap]);
2991 case BCM4329_CHIP_ID:
2992 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >=
2993 sizeof(cis_sel)) ? CIS_DEFAULT : cis_sel[(sih->
2994 chipst &
2995 CST4329_SPROM_OTP_SEL_MASK)];
2996 case BCM4319_CHIP_ID:{
2997 uint cis_sel4319 =
2998 ((sih->
2999 chipst & CST4319_SPROM_OTP_SEL_MASK) >>
3000 CST4319_SPROM_OTP_SEL_SHIFT);
3001 return (cis_sel4319 >=
3002 sizeof(cis_sel)) ? CIS_DEFAULT :
3003 cis_sel[cis_sel4319];
3005 case BCM4336_CHIP_ID:{
3006 if (sih->chipst & CST4336_SPROM_PRESENT)
3007 return CIS_SROM;
3008 if (sih->chipst & CST4336_OTP_PRESENT)
3009 return CIS_OTP;
3010 return CIS_DEFAULT;
3012 case BCM4330_CHIP_ID:{
3013 if (sih->chipst & CST4330_SPROM_PRESENT)
3014 return CIS_SROM;
3015 if (sih->chipst & CST4330_OTP_PRESENT)
3016 return CIS_OTP;
3017 return CIS_DEFAULT;
3019 default:
3020 return CIS_DEFAULT;