bccd3c28a8849f346a46af155324e30922d4f2be
[pandora-kernel.git] / drivers / staging / brcm80211 / util / siutils.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
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.
7  *
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.
15  */
16
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>
45
46 /* this file now contains only definitions for sb functions, only necessary
47 *for devices using Sonics backplanes (bcm4329)
48 */
49
50 /* if an amba SDIO device is supported, please further restrict the inclusion
51  * of this file
52  */
53 #ifdef BCMSDIO
54 #include "siutils_priv.h"
55 #endif
56
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);
66
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);
73
74 /* global variable to indicate reservation/release of gpio's */
75 static uint32 si_gpioreservation;
76
77 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
78
79 /*
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
87  */
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;
92
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;
99         }
100
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;
105         }
106         sii->vars = vars ? *vars : NULL;
107         sii->varsz = varsz ? *varsz : 0;
108
109         return (si_t *) sii;
110 }
111
112 /* global kernel resource */
113 static si_info_t ksii;
114
115 static uint32 wd_msticks;       /* watchdog timer ticks normalized to ms */
116
117 static bool
118 BCMATTACHFN(si_buscore_prep) (si_info_t *sii, uint bustype, uint devid,
119                               void *sdh) {
120
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
126
127 #if defined(BCMSDIO)
128         if (BUSTYPE(bustype) == SDIO_BUS) {
129                 int err;
130                 u8 clkset;
131
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;
138
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;
153                                 }
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);
161                         }
162                 }
163
164                 /* Also, disable the extra SDIO pull-ups */
165                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
166                                  NULL);
167         }
168 #endif                          /* defined(BCMSDIO) */
169
170         return TRUE;
171 }
172
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;
179
180         cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
181         ASSERT((uintptr) cc);
182
183         /* get chipcommon rev */
184         sii->pub.ccrev = (int)si_corerev(&sii->pub);
185
186         /* get chipcommon chipstatus */
187         if (sii->pub.ccrev >= 11)
188                 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
189
190         /* get chipcommon capabilites */
191         sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
192         /* get chipcommon extended capabilities */
193
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;
202         }
203
204         /*
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));
208          */
209
210         /* figure out bus/orignal core idx */
211         sii->pub.buscoretype = NODEV_CORE_ID;
212         sii->pub.buscorerev = NOREV;
213         sii->pub.buscoreidx = BADIDX;
214
215         pci = pcie = FALSE;
216         pcirev = pcierev = NOREV;
217         pciidx = pcieidx = BADIDX;
218
219         for (i = 0; i < sii->numcores; i++) {
220                 uint cid, crev;
221
222                 si_setcoreidx(&sii->pub, i);
223                 cid = si_coreid(&sii->pub);
224                 crev = si_corerev(&sii->pub);
225
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]));
229
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;
239                         }
240                 }
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;
248                 }
249 #endif                          /* BCMSDIO */
250
251                 /* find the core idx before entering this func. */
252                 if ((savewin && (savewin == sii->coresba[i])) ||
253                     (regs == sii->regs[i]))
254                         *origidx = i;
255         }
256
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));
260
261         /* Make sure any on-chip ARM is off (in case strapping is wrong),
262         * or downloaded code was
263         * already running.
264         */
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);
269         }
270 #else
271         if (pci && pcie) {
272                 if (si_ispcie(sii))
273                         pci = FALSE;
274                 else
275                         pcie = FALSE;
276         }
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;
285         }
286
287         SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
288                  sii->pub.buscoretype, sii->pub.buscorerev));
289
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;
299                         }
300                 }
301                 if (si_pci_fixcfg(&sii->pub)) {
302                         SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
303                         return FALSE;
304                 }
305         }
306 #endif
307         /* return to the original core */
308         si_setcoreidx(&sii->pub, *origidx);
309
310         return TRUE;
311 }
312
313 static __used void BCMATTACHFN(si_nvram_process) (si_info_t *sii, char *pvars)
314 {
315         uint w = 0;
316
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;
336
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;
343
344 #ifdef BCMSDIO
345         case SPI_BUS:
346                 sii->pub.boardvendor = VENDOR_BROADCOM;
347                 sii->pub.boardtype = SPI_BOARD;
348                 break;
349 #endif
350
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;
359                 }
360                 break;
361         }
362
363         if (sii->pub.boardtype == 0) {
364                 SI_ERROR(("si_doattach: unknown board type\n"));
365                 ASSERT(sii->pub.boardtype);
366         }
367
368         sii->pub.boardflags = getintvar(pvars, "boardflags");
369 }
370
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;
383
384         ASSERT(GOODREGS(regs));
385
386         bzero((uchar *) sii, sizeof(si_info_t));
387
388         savewin = 0;
389
390         sih->buscoreidx = BADIDX;
391
392         sii->curmap = regs;
393         sii->sdh = sdh;
394         sii->osh = osh;
395
396         /* find Chipcommon address */
397         cc = (chipcregs_t *) sii->curmap;
398         sih->bustype = bustype;
399
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;
403         }
404
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;
410         }
411
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.
416          */
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;
423
424         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) &&
425                 (sih->chippkg != BCM4329_289PIN_PKG_ID))
426                         sih->chippkg = BCM4329_182PIN_PKG_ID;
427
428         sih->issim = IS_SIM(sih->chippkg);
429
430         /* scan for cores */
431         /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
432         sb_scan(&sii->pub, regs, devid);
433
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;
438         }
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;
444         }
445
446 #ifdef BRCM_FULLMAC
447         pvars = NULL;
448 #else
449         /* Init nvram from flash if it exists */
450         nvram_init((void *)&(sii->pub));
451
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;
457         }
458         pvars = vars ? *vars : NULL;
459         si_nvram_process(sii, pvars);
460 #endif
461
462         /* === NVRAM, clock is ready === */
463
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
472         }
473 #endif
474
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);
488         }
489
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);
495
496 #ifdef BCMDBG
497         /* clear any previous epidiag-induced target abort */
498         sb_taclear(sih, FALSE);
499 #endif                          /* BCMDBG */
500 #endif
501
502         return sii;
503
504  exit:
505         return NULL;
506 }
507
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;
518
519         ASSERT(GOODREGS(regs));
520
521         bzero((uchar *) sii, sizeof(si_info_t));
522
523         savewin = 0;
524
525         sih->buscoreidx = BADIDX;
526
527         sii->curmap = regs;
528         sii->sdh = sdh;
529         sii->osh = osh;
530
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;
537         }
538
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);
549         }
550
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;
555         }
556
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;
562         }
563
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.
568          */
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;
575
576         sih->issim = IS_SIM(sih->chippkg);
577
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;
586         }
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;
591         }
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;
597         }
598
599         /* assume current core is CC */
600         if ((sii->pub.ccrev == 0x25)
601             &&
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))) {
606
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));
614                 }
615                 OSL_DELAY(10);
616         }
617
618         /* Init nvram from flash if it exists */
619         nvram_init((void *)&(sii->pub));
620
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;
626         }
627         pvars = vars ? *vars : NULL;
628         si_nvram_process(sii, pvars);
629
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);
635
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);
648         }
649
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);
655
656         if (PCIE(sii)) {
657                 ASSERT(sii->pch != NULL);
658                 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
659         }
660
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);
672                 }
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);
677                 }
678         }
679
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);
685         }
686
687         if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
688                 /* Enable Ext PA lines depending on chip package option */
689                 si_chipcontrl_epa4331(sih, TRUE);
690         }
691
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;
698         }
699
700         return NULL;
701 }
702 #endif                          /* BCMSDIO */
703
704 /* may be called with core in reset */
705 void BCMATTACHFN(si_detach) (si_t *sih)
706 {
707         si_info_t *sii;
708         uint idx;
709
710         struct si_pub *si_local = NULL;
711         bcopy(&sih, &si_local, sizeof(si_t **));
712
713         sii = SI_INFO(sih);
714
715         if (sii == NULL)
716                 return;
717
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;
723                         }
724
725 #ifndef BRCM_FULLMAC
726         nvram_exit((void *)si_local);   /* free up nvram buffers */
727
728         if (BUSTYPE(sih->bustype) == PCI_BUS) {
729                 if (sii->pch)
730                         pcicore_deinit(sii->pch);
731                 sii->pch = NULL;
732         }
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));
738 }
739
740 void *si_osh(si_t *sih)
741 {
742         si_info_t *sii;
743
744         sii = SI_INFO(sih);
745         return sii->osh;
746 }
747
748 void si_setosh(si_t *sih, osl_t *osh)
749 {
750         si_info_t *sii;
751
752         sii = SI_INFO(sih);
753         if (sii->osh != NULL) {
754                 SI_ERROR(("osh is already set....\n"));
755                 ASSERT(!sii->osh);
756         }
757         sii->osh = osh;
758 }
759
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)
764 {
765         si_info_t *sii;
766
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.)
774          */
775         sii->dev_coreid = sii->coreid[sii->curidx];
776 }
777
778 void si_deregister_intr_callback(si_t *sih)
779 {
780         si_info_t *sii;
781
782         sii = SI_INFO(sih);
783         sii->intrsoff_fn = NULL;
784 }
785
786 uint si_intflag(si_t *sih)
787 {
788         si_info_t *sii = SI_INFO(sih);
789
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;
797         }
798 }
799
800 uint si_flag(si_t *sih)
801 {
802         if (CHIPTYPE(sih->socitype) == SOCI_AI)
803                 return ai_flag(sih);
804         else {
805                 ASSERT(0);
806                 return 0;
807         }
808 }
809
810 void si_setint(si_t *sih, int siflag)
811 {
812         if (CHIPTYPE(sih->socitype) == SOCI_AI)
813                 ai_setint(sih, siflag);
814         else
815                 ASSERT(0);
816 }
817
818 #ifndef BCMSDIO
819 uint si_coreid(si_t *sih)
820 {
821         si_info_t *sii;
822
823         sii = SI_INFO(sih);
824         return sii->coreid[sii->curidx];
825 }
826 #endif
827
828 uint si_coreidx(si_t *sih)
829 {
830         si_info_t *sii;
831
832         sii = SI_INFO(sih);
833         return sii->curidx;
834 }
835
836 /* return the core-type instantiation # of the current core */
837 uint si_coreunit(si_t *sih)
838 {
839         si_info_t *sii;
840         uint idx;
841         uint coreid;
842         uint coreunit;
843         uint i;
844
845         sii = SI_INFO(sih);
846         coreunit = 0;
847
848         idx = sii->curidx;
849
850         ASSERT(GOODREGS(sii->curmap));
851         coreid = si_coreid(sih);
852
853         /* count the cores of our type */
854         for (i = 0; i < idx; i++)
855                 if (sii->coreid[i] == coreid)
856                         coreunit++;
857
858         return coreunit;
859 }
860
861 uint si_corevendor(si_t *sih)
862 {
863         if (CHIPTYPE(sih->socitype) == SOCI_AI)
864                 return ai_corevendor(sih);
865         else {
866                 ASSERT(0);
867                 return 0;
868         }
869 }
870
871 bool si_backplane64(si_t *sih)
872 {
873         return (sih->cccaps & CC_CAP_BKPLN64) != 0;
874 }
875
876 #ifndef BCMSDIO
877 uint si_corerev(si_t *sih)
878 {
879         if (CHIPTYPE(sih->socitype) == SOCI_AI)
880                 return ai_corerev(sih);
881         else {
882                 ASSERT(0);
883                 return 0;
884         }
885 }
886 #endif
887
888 /* return index of coreid or BADIDX if not found */
889 uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
890 {
891         si_info_t *sii;
892         uint found;
893         uint i;
894
895         sii = SI_INFO(sih);
896
897         found = 0;
898
899         for (i = 0; i < sii->numcores; i++)
900                 if (sii->coreid[i] == coreid) {
901                         if (found == coreunit)
902                                 return i;
903                         found++;
904                 }
905
906         return BADIDX;
907 }
908
909 /* return list of found cores */
910 uint si_corelist(si_t *sih, uint coreid[])
911 {
912         si_info_t *sii;
913
914         sii = SI_INFO(sih);
915
916         bcopy((uchar *) sii->coreid, (uchar *) coreid,
917               (sii->numcores * sizeof(uint)));
918         return sii->numcores;
919 }
920
921 /* return current register mapping */
922 void *si_coreregs(si_t *sih)
923 {
924         si_info_t *sii;
925
926         sii = SI_INFO(sih);
927         ASSERT(GOODREGS(sii->curmap));
928
929         return sii->curmap;
930 }
931
932 /*
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
936  */
937 void *si_setcore(si_t *sih, uint coreid, uint coreunit)
938 {
939         uint idx;
940
941         idx = si_findcoreidx(sih, coreid, coreunit);
942         if (!GOODIDX(idx))
943                 return NULL;
944
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
954         }
955 }
956
957 #ifndef BCMSDIO
958 void *si_setcoreidx(si_t *sih, uint coreidx)
959 {
960         if (CHIPTYPE(sih->socitype) == SOCI_AI)
961                 return ai_setcoreidx(sih, coreidx);
962         else {
963                 ASSERT(0);
964                 return NULL;
965         }
966 }
967 #endif
968
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)
971 {
972         void *cc;
973         si_info_t *sii;
974
975         sii = SI_INFO(sih);
976
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.
981                  */
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);
987         }
988         INTR_OFF(sii, *intr_val);
989         *origidx = sii->curidx;
990         cc = si_setcore(sih, coreid, 0);
991         ASSERT(cc != NULL);
992
993         return cc;
994 }
995
996 /* restore coreidx and restore interrupt */
997 void si_restore_core(si_t *sih, uint coreid, uint intr_val)
998 {
999         si_info_t *sii;
1000
1001         sii = SI_INFO(sih);
1002         if (SI_FAST(sii)
1003             && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1004                 return;
1005
1006         si_setcoreidx(sih, coreid);
1007         INTR_RESTORE(sii, intr_val);
1008 }
1009
1010 int si_numaddrspaces(si_t *sih)
1011 {
1012         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1013                 return ai_numaddrspaces(sih);
1014         else {
1015                 ASSERT(0);
1016                 return 0;
1017         }
1018 }
1019
1020 uint32 si_addrspace(si_t *sih, uint asidx)
1021 {
1022         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1023                 return ai_addrspace(sih, asidx);
1024         else {
1025                 ASSERT(0);
1026                 return 0;
1027         }
1028 }
1029
1030 uint32 si_addrspacesize(si_t *sih, uint asidx)
1031 {
1032         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1033                 return ai_addrspacesize(sih, asidx);
1034         else {
1035                 ASSERT(0);
1036                 return 0;
1037         }
1038 }
1039
1040 uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1041 {
1042         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1043                 return ai_core_cflags(sih, mask, val);
1044         else {
1045                 ASSERT(0);
1046                 return 0;
1047         }
1048 }
1049
1050 void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1051 {
1052         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1053                 ai_core_cflags_wo(sih, mask, val);
1054         else
1055                 ASSERT(0);
1056 }
1057
1058 uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1059 {
1060         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1061                 return ai_core_sflags(sih, mask, val);
1062         else {
1063                 ASSERT(0);
1064                 return 0;
1065         }
1066 }
1067
1068 bool si_iscoreup(si_t *sih)
1069 {
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
1079         }
1080 }
1081
1082 void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1083 {
1084         /* only for 4319, no requirement for SOCI_SB */
1085         if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1086                 ai_write_wrap_reg(sih, offset, val);
1087         }
1088 }
1089
1090 uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1091 {
1092
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
1102         }
1103 }
1104
1105 void si_core_disable(si_t *sih, uint32 bits)
1106 {
1107
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
1114 }
1115
1116 void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1117 {
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
1124 }
1125
1126 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1127 int si_corebist(si_t *sih)
1128 {
1129         uint32 cflags;
1130         int result = 0;
1131
1132         /* Read core control flags */
1133         cflags = si_core_cflags(sih, 0, 0);
1134
1135         /* Set bist & fgc */
1136         si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1137
1138         /* Wait for bist done */
1139         SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1140
1141         if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1142                 result = BCME_ERROR;
1143
1144         /* Reset core control flags */
1145         si_core_cflags(sih, 0xffff, cflags);
1146
1147         return result;
1148 }
1149
1150 static uint32 BCMINITFN(factor6) (uint32 x)
1151 {
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;
1167         }
1168 }
1169
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)
1172 {
1173         uint32 n1, n2, clock, m1, m2, m3, mc;
1174
1175         n1 = n & CN_N1_MASK;
1176         n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1177
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;
1202
1203         if (clock == 0)
1204                 return 0;
1205
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;
1210
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);
1220
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;
1234                 }
1235         } else {
1236                 ASSERT(pll_type == PLL_TYPE2);
1237
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));
1244
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;
1251
1252                 return clock;
1253         }
1254 }
1255
1256 uint32 BCMINITFN(si_clock) (si_t *sih)
1257 {
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;
1264
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;
1270         }
1271
1272         idx = sii->curidx;
1273         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1274         ASSERT(cc != NULL);
1275
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);
1284
1285         /* calculate rate */
1286         rate = si_clock_rate(pll_type, n, m);
1287
1288         if (pll_type == PLL_TYPE3)
1289                 rate = rate / 2;
1290
1291         /* switch back to previous core */
1292         si_setcoreidx(sih, idx);
1293  exit:
1294         INTR_RESTORE(sii, intr_val);
1295
1296         return rate;
1297 }
1298
1299 uint32 BCMINITFN(si_alp_clock) (si_t *sih)
1300 {
1301         if (PMUCTL_ENAB(sih))
1302                 return si_pmu_alp_clock(sih, si_osh(sih));
1303
1304         return ALP_CLOCK;
1305 }
1306
1307 uint32 BCMINITFN(si_ilp_clock) (si_t *sih)
1308 {
1309         if (PMUCTL_ENAB(sih))
1310                 return si_pmu_ilp_clock(sih, si_osh(sih));
1311
1312         return ILP_CLOCK;
1313 }
1314
1315 /* set chip watchdog reset timer to fire in 'ticks' */
1316 #ifdef BRCM_FULLMAC
1317 void
1318 si_watchdog(si_t *sih, uint ticks)
1319 {
1320         if (PMUCTL_ENAB(sih)) {
1321
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);
1329                 }
1330
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);
1339         }
1340 }
1341 #else
1342 void si_watchdog(si_t *sih, uint ticks)
1343 {
1344         uint nb, maxt;
1345
1346         if (PMUCTL_ENAB(sih)) {
1347
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);
1355                 }
1356
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.
1360                  */
1361                 if (nb == 32)
1362                         maxt = 0xffffffff;
1363                 else
1364                         maxt = ((1 << nb) - 1);
1365
1366                 if (ticks == 1)
1367                         ticks = 2;
1368                 else if (ticks > maxt)
1369                         ticks = maxt;
1370
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;
1379
1380                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
1381                            ticks);
1382         }
1383 }
1384 #endif
1385
1386 /* trigger watchdog reset after ms milliseconds */
1387 void si_watchdog_ms(si_t *sih, uint32 ms)
1388 {
1389         si_watchdog(sih, wd_msticks * ms);
1390 }
1391
1392 uint16 BCMATTACHFN(si_d11_devid) (si_t *sih)
1393 {
1394         si_info_t *sii = SI_INFO(sih);
1395         uint16 device;
1396
1397         /* normal case: nvram variable with devpath->devid->wl0id */
1398         device = (uint16) si_getdevpathintvar(sih, "devid");
1399         if (device != 0)
1400                 goto bail;
1401
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;
1406
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;
1411
1412         /* ignore it */
1413         device = 0xffff;
1414
1415 bail:
1416         return device;
1417 }
1418
1419 /* return the slow clock source - LPO, XTAL, or PCI */
1420 static uint si_slowclk_src(si_info_t *sii)
1421 {
1422         chipcregs_t *cc;
1423
1424         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1425
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;
1438 }
1439
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)
1442 {
1443         uint32 slowclk;
1444         uint div;
1445
1446         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1447
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);
1450
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);
1478         }
1479         return 0;
1480 }
1481
1482 static void BCMINITFN(si_clkctl_setdelay) (si_info_t *sii, void *chipcregs)
1483 {
1484         chipcregs_t *cc = (chipcregs_t *) chipcregs;
1485         uint slowmaxfreq, pll_delay, slowclk;
1486         uint pll_on_delay, fref_sel_delay;
1487
1488         pll_delay = PLL_DELAY;
1489
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.
1492          */
1493
1494         slowclk = si_slowclk_src(sii);
1495         if (slowclk != SCC_SS_XTAL)
1496                 pll_delay += XTAL_ON_DELAY;
1497
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);
1501
1502         pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1503         fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1504
1505         W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1506         W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1507 }
1508
1509 /* initialize power control delay registers */
1510 void BCMINITFN(si_clkctl_init) (si_t *sih)
1511 {
1512         si_info_t *sii;
1513         uint origidx = 0;
1514         chipcregs_t *cc;
1515         bool fast;
1516
1517         if (!CCCTL_ENAB(sih))
1518                 return;
1519
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;
1531         }
1532         ASSERT(cc != NULL);
1533
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));
1538
1539         si_clkctl_setdelay(sii, (void *)(uintptr) cc);
1540
1541         if (!fast)
1542                 si_setcoreidx(sih, origidx);
1543 }
1544
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)
1547 {
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;
1555
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;
1562         }
1563
1564         if (!CCCTL_ENAB(sih))
1565                 return 0;
1566
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;
1579         }
1580         ASSERT(cc != NULL);
1581
1582         slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1583         fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1584                    (slowminfreq - 1)) / slowminfreq;
1585
1586  done:
1587         if (!fast) {
1588                 si_setcoreidx(sih, origidx);
1589                 INTR_RESTORE(sii, intr_val);
1590         }
1591         return fpdelay;
1592 }
1593
1594 /* turn primary xtal and/or pll off/on */
1595 int si_clkctl_xtal(si_t *sih, uint what, bool on)
1596 {
1597         si_info_t *sii;
1598         uint32 in, out, outen;
1599
1600         sii = SI_INFO(sih);
1601
1602         switch (BUSTYPE(sih->bustype)) {
1603
1604 #ifdef BCMSDIO
1605         case SDIO_BUS:
1606                 return -1;
1607 #endif                          /* BCMSDIO */
1608
1609         case PCI_BUS:
1610                 /* pcie core doesn't have any mapping to control the xtal pu */
1611                 if (PCIE(sii))
1612                         return -1;
1613
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));
1620
1621                 /*
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.
1625                  */
1626                 if (on && (in & PCI_CFG_GPIO_XTAL))
1627                         return 0;
1628
1629                 if (what & XTAL)
1630                         outen |= PCI_CFG_GPIO_XTAL;
1631                 if (what & PLL)
1632                         outen |= PCI_CFG_GPIO_PLL;
1633
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);
1645                         }
1646
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);
1653                         }
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);
1663                 }
1664
1665         default:
1666                 return -1;
1667         }
1668
1669         return 0;
1670 }
1671
1672 /*
1673  *  clock control policy function throught chipcommon
1674  *
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
1679  */
1680 bool si_clkctl_cc(si_t *sih, uint mode)
1681 {
1682         si_info_t *sii;
1683
1684         sii = SI_INFO(sih);
1685
1686         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1687         if (sih->ccrev < 6)
1688                 return FALSE;
1689
1690         if (PCI_FORCEHT(sii))
1691                 return mode == CLK_FAST;
1692
1693         return _si_clkctl_cc(sii, mode);
1694 }
1695
1696 /* clk control mechanism through chipcommon, no policy checking */
1697 static bool _si_clkctl_cc(si_info_t *sii, uint mode)
1698 {
1699         uint origidx = 0;
1700         chipcregs_t *cc;
1701         uint32 scc;
1702         uint intr_val = 0;
1703         bool fast = SI_FAST(sii);
1704
1705         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1706         if (sii->pub.ccrev < 6)
1707                 return FALSE;
1708
1709         /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1710         ASSERT(sii->pub.ccrev != 10);
1711
1712         if (!fast) {
1713                 INTR_OFF(sii, intr_val);
1714                 origidx = sii->curidx;
1715
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;
1720
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;
1726         }
1727         ASSERT(cc != NULL);
1728
1729         if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1730                 goto done;
1731
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);
1743                 }
1744
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);
1753                 }
1754                 break;
1755
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);
1763
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);
1772                 }
1773                 break;
1774
1775         default:
1776                 ASSERT(0);
1777         }
1778
1779  done:
1780         if (!fast) {
1781                 si_setcoreidx(&sii->pub, origidx);
1782                 INTR_RESTORE(sii, intr_val);
1783         }
1784         return mode == CLK_FAST;
1785 }
1786
1787 /* Build device path. Support SI, PCI, and JTAG for now. */
1788 int BCMATTACHFN(si_devpath) (si_t *sih, char *path, int size)
1789 {
1790         int slen;
1791
1792         ASSERT(path != NULL);
1793         ASSERT(size >= SI_DEVPATH_BUFSZ);
1794
1795         if (!path || size <= 0)
1796                 return -1;
1797
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;
1809
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;
1820         }
1821
1822         if (slen < 0 || slen >= size) {
1823                 path[0] = '\0';
1824                 return -1;
1825         }
1826
1827         return 0;
1828 }
1829
1830 /* Get a variable, but only if it has a devpath prefix */
1831 char *BCMATTACHFN(si_getdevpathvar) (si_t *sih, const char *name)
1832 {
1833         char varname[SI_DEVPATH_BUFSZ + 32];
1834
1835         si_devpathvar(sih, varname, sizeof(varname), name);
1836
1837         return getvar(NULL, varname);
1838 }
1839
1840 /* Get a variable, but only if it has a devpath prefix */
1841 int BCMATTACHFN(si_getdevpathintvar) (si_t *sih, const char *name)
1842 {
1843 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1844         return getintvar(NULL, name);
1845 #else
1846         char varname[SI_DEVPATH_BUFSZ + 32];
1847
1848         si_devpathvar(sih, varname, sizeof(varname), name);
1849
1850         return getintvar(NULL, varname);
1851 #endif
1852 }
1853
1854 char *si_getnvramflvar(si_t *sih, const char *name)
1855 {
1856         return getvar(NULL, name);
1857 }
1858
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'.
1863  */
1864 static char *BCMATTACHFN(si_devpathvar) (si_t *sih, char *var, int len,
1865                                          const char *name) {
1866         uint path_len;
1867
1868         if (!var || len <= 0)
1869                 return var;
1870
1871         if (si_devpath(sih, var, len) == 0) {
1872                 path_len = strlen(var);
1873
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);
1878         }
1879
1880         return var;
1881 }
1882
1883 uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
1884 {
1885         si_info_t *sii;
1886
1887         sii = SI_INFO(sih);
1888
1889         if (!PCIE(sii)) {
1890                 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1891                 return 0;
1892         }
1893
1894         return pcicore_pciereg(sii->pch, offset, mask, val, type);
1895 }
1896
1897 uint32
1898 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask,
1899                  uint32 val)
1900 {
1901         si_info_t *sii;
1902
1903         sii = SI_INFO(sih);
1904
1905         if (!PCIE(sii)) {
1906                 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1907                 return 0;
1908         }
1909
1910         return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
1911
1912 }
1913
1914 /* return TRUE if PCIE capability exists in the pci config space */
1915 static __used bool si_ispcie(si_info_t *sii)
1916 {
1917         u8 cap_ptr;
1918
1919         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1920                 return FALSE;
1921
1922         cap_ptr =
1923             pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1924                                         NULL);
1925         if (!cap_ptr)
1926                 return FALSE;
1927
1928         return TRUE;
1929 }
1930
1931 /* Wake-on-wireless-LAN (WOWL) support functions */
1932 /* Enable PME generation and disable clkreq */
1933 void si_pci_pmeen(si_t *sih)
1934 {
1935         si_info_t *sii;
1936
1937         sii = SI_INFO(sih);
1938
1939         pcicore_pmeen(sii->pch);
1940 }
1941
1942 /* Return TRUE if PME status is set */
1943 bool si_pci_pmestat(si_t *sih)
1944 {
1945         si_info_t *sii;
1946
1947         sii = SI_INFO(sih);
1948
1949         return pcicore_pmestat(sii->pch);
1950 }
1951
1952 /* Disable PME generation, clear the PME status bit if set */
1953 void si_pci_pmeclr(si_t *sih)
1954 {
1955         si_info_t *sii;
1956
1957         sii = SI_INFO(sih);
1958
1959         pcicore_pmeclr(sii->pch);
1960 }
1961
1962 #ifdef BCMSDIO
1963 /* initialize the sdio core */
1964 void si_sdio_init(si_t *sih)
1965 {
1966         si_info_t *sii = SI_INFO(sih);
1967
1968         if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1969             (sih->buscoretype == SDIOD_CORE_ID)) {
1970                 uint idx;
1971                 sdpcmd_regs_t *sdpregs;
1972
1973                 /* get the current core index */
1974                 idx = sii->curidx;
1975                 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1976
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);
1983
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));
1985
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)));
1990
1991                 /* switch back to previous core */
1992                 si_setcoreidx(sih, idx);
1993         }
1994
1995         /* enable interrupts */
1996         bcmsdh_intr_enable(sii->sdh);
1997
1998 }
1999 #endif                          /* BCMSDIO */
2000
2001 bool BCMATTACHFN(si_pci_war16165) (si_t *sih)
2002 {
2003         si_info_t *sii;
2004
2005         sii = SI_INFO(sih);
2006
2007         return PCI(sii) && (sih->buscorerev <= 10);
2008 }
2009
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
2014  */
2015 void si_pcie_war_ovr_update(si_t *sih, u8 aspm)
2016 {
2017         si_info_t *sii;
2018
2019         sii = SI_INFO(sih);
2020
2021         if (!PCIE(sii))
2022                 return;
2023
2024         pcie_war_ovr_aspm_update(sii->pch, aspm);
2025 }
2026
2027 /* back door for other module to override chippkg */
2028 void si_chippkg_set(si_t *sih, uint val)
2029 {
2030         si_info_t *sii;
2031
2032         sii = SI_INFO(sih);
2033
2034         sii->pub.chippkg = val;
2035 }
2036
2037 void BCMINITFN(si_pci_up) (si_t *sih)
2038 {
2039         si_info_t *sii;
2040
2041         sii = SI_INFO(sih);
2042
2043         /* if not pci bus, we're done */
2044         if (BUSTYPE(sih->bustype) != PCI_BUS)
2045                 return;
2046
2047         if (PCI_FORCEHT(sii))
2048                 _si_clkctl_cc(sii, CLK_FAST);
2049
2050         if (PCIE(sii))
2051                 pcicore_up(sii->pch, SI_PCIUP);
2052
2053 }
2054
2055 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2056 void BCMUNINITFN(si_pci_sleep) (si_t *sih)
2057 {
2058         si_info_t *sii;
2059
2060         sii = SI_INFO(sih);
2061
2062         pcicore_sleep(sii->pch);
2063 }
2064
2065 /* Unconfigure and/or apply various WARs when going down */
2066 void BCMINITFN(si_pci_down) (si_t *sih)
2067 {
2068         si_info_t *sii;
2069
2070         sii = SI_INFO(sih);
2071
2072         /* if not pci bus, we're done */
2073         if (BUSTYPE(sih->bustype) != PCI_BUS)
2074                 return;
2075
2076         /* release FORCEHT since chip is going to "down" state */
2077         if (PCI_FORCEHT(sii))
2078                 _si_clkctl_cc(sii, CLK_DYNAMIC);
2079
2080         pcicore_down(sii->pch, SI_PCIDOWN);
2081 }
2082
2083 /*
2084  * Configure the pci core for pci client (NIC) action
2085  * coremask is the bitvec of cores by index to be enabled.
2086  */
2087 void BCMATTACHFN(si_pci_setup) (si_t *sih, uint coremask)
2088 {
2089         si_info_t *sii;
2090         sbpciregs_t *pciregs = NULL;
2091         uint32 siflag = 0, w;
2092         uint idx = 0;
2093
2094         sii = SI_INFO(sih);
2095
2096         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2097                 return;
2098
2099         ASSERT(PCI(sii) || PCIE(sii));
2100         ASSERT(sii->pub.buscoreidx != BADIDX);
2101
2102         if (PCI(sii)) {
2103                 /* get current core index */
2104                 idx = sii->curidx;
2105
2106                 /* we interrupt on this backplane flag number */
2107                 siflag = si_flag(sih);
2108
2109                 /* switch over to pci core */
2110                 pciregs =
2111                     (sbpciregs_t *) si_setcoreidx(sih, sii->pub.buscoreidx);
2112         }
2113
2114         /*
2115          * Enable sb->pci interrupts.  Assume
2116          * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2117          */
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);
2126         }
2127
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);
2138                 }
2139
2140                 /* switch back to previous core */
2141                 si_setcoreidx(sih, idx);
2142         }
2143 }
2144
2145 u8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2146 {
2147         si_info_t *sii;
2148
2149         sii = SI_INFO(sih);
2150
2151         if (!(PCIE(sii)))
2152                 return 0;
2153         return pcie_clkreq(sii->pch, mask, val);
2154 }
2155
2156 uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2157 {
2158         si_info_t *sii;
2159
2160         sii = SI_INFO(sih);
2161
2162         if (!PCIE(sii))
2163                 return 0;
2164
2165         return pcie_lcreg(sii->pch, mask, val);
2166 }
2167
2168 /* indirect way to read pcie config regs */
2169 uint si_pcie_readreg(void *sih, uint addrtype, uint offset)
2170 {
2171         return pcie_readreg(((si_info_t *) sih)->osh,
2172                             (sbpcieregs_t *) PCIEREGS(((si_info_t *) sih)),
2173                             addrtype, offset);
2174 }
2175
2176 /*
2177  * Fixup SROMless PCI device's configuration.
2178  * The current core may be changed upon return.
2179  */
2180 int si_pci_fixcfg(si_t *sih)
2181 {
2182         uint origidx, pciidx;
2183         sbpciregs_t *pciregs = NULL;
2184         sbpcieregs_t *pcieregs = NULL;
2185         void *regs = NULL;
2186         uint16 val16, *reg16 = NULL;
2187
2188         si_info_t *sii = SI_INFO(sih);
2189
2190         ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2191
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);
2195
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];
2208         }
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);
2216         }
2217
2218         /* restore the original index */
2219         si_setcoreidx(&sii->pub, origidx);
2220
2221         pcicore_hwup(sii->pch);
2222         return 0;
2223 }
2224
2225 /* change logical "focus" to the gpio core for optimized access */
2226 void *si_gpiosetcore(si_t *sih)
2227 {
2228         return si_setcoreidx(sih, SI_CC_IDX);
2229 }
2230
2231 /* mask&set gpiocontrol bits */
2232 uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, u8 priority)
2233 {
2234         uint regoff;
2235
2236         regoff = 0;
2237
2238         /* gpios could be shared on router platforms
2239          * ignore reservation if it's high priority (e.g., test apps)
2240          */
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;
2246         }
2247
2248         regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2249         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2250 }
2251
2252 /* mask&set gpio output enable bits */
2253 uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, u8 priority)
2254 {
2255         uint regoff;
2256
2257         regoff = 0;
2258
2259         /* gpios could be shared on router platforms
2260          * ignore reservation if it's high priority (e.g., test apps)
2261          */
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;
2267         }
2268
2269         regoff = OFFSETOF(chipcregs_t, gpioouten);
2270         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2271 }
2272
2273 /* mask&set gpio output bits */
2274 uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, u8 priority)
2275 {
2276         uint regoff;
2277
2278         regoff = 0;
2279
2280         /* gpios could be shared on router platforms
2281          * ignore reservation if it's high priority (e.g., test apps)
2282          */
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;
2288         }
2289
2290         regoff = OFFSETOF(chipcregs_t, gpioout);
2291         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2292 }
2293
2294 /* reserve one gpio */
2295 uint32 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, u8 priority)
2296 {
2297         si_info_t *sii;
2298
2299         sii = SI_INFO(sih);
2300
2301         /* only cores on SI_BUS share GPIO's and only applcation users need to
2302          * reserve/release GPIO
2303          */
2304         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2305                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2306                 return 0xffffffff;
2307         }
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;
2313         }
2314
2315         /* already reserved */
2316         if (si_gpioreservation & gpio_bitmask)
2317                 return 0xffffffff;
2318         /* set reservation */
2319         si_gpioreservation |= gpio_bitmask;
2320
2321         return si_gpioreservation;
2322 }
2323
2324 /* release one gpio */
2325 /*
2326  * releasing the gpio doesn't change the current value on the GPIO last write value
2327  * persists till some one overwrites it
2328  */
2329
2330 uint32 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, u8 priority)
2331 {
2332         si_info_t *sii;
2333
2334         sii = SI_INFO(sih);
2335
2336         /* only cores on SI_BUS share GPIO's and only applcation users need to
2337          * reserve/release GPIO
2338          */
2339         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2340                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2341                 return 0xffffffff;
2342         }
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;
2348         }
2349
2350         /* already released */
2351         if (!(si_gpioreservation & gpio_bitmask))
2352                 return 0xffffffff;
2353
2354         /* clear reservation */
2355         si_gpioreservation &= ~gpio_bitmask;
2356
2357         return si_gpioreservation;
2358 }
2359
2360 /* return the current gpioin register value */
2361 uint32 si_gpioin(si_t *sih)
2362 {
2363         si_info_t *sii;
2364         uint regoff;
2365
2366         sii = SI_INFO(sih);
2367         regoff = 0;
2368
2369         regoff = OFFSETOF(chipcregs_t, gpioin);
2370         return si_corereg(sih, SI_CC_IDX, regoff, 0, 0);
2371 }
2372
2373 /* mask&set gpio interrupt polarity bits */
2374 uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, u8 priority)
2375 {
2376         si_info_t *sii;
2377         uint regoff;
2378
2379         sii = SI_INFO(sih);
2380         regoff = 0;
2381
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;
2387         }
2388
2389         regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2390         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2391 }
2392
2393 /* mask&set gpio interrupt mask bits */
2394 uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, u8 priority)
2395 {
2396         si_info_t *sii;
2397         uint regoff;
2398
2399         sii = SI_INFO(sih);
2400         regoff = 0;
2401
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;
2407         }
2408
2409         regoff = OFFSETOF(chipcregs_t, gpiointmask);
2410         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
2411 }
2412
2413 /* assign the gpio to an led */
2414 uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val)
2415 {
2416         si_info_t *sii;
2417
2418         sii = SI_INFO(sih);
2419         if (sih->ccrev < 16)
2420                 return 0xffffffff;
2421
2422         /* gpio led powersave reg */
2423         return si_corereg
2424                 (sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
2425                  val);
2426 }
2427
2428 /* mask&set gpio timer val */
2429 uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2430 {
2431         si_info_t *sii;
2432
2433         sii = SI_INFO(sih);
2434
2435         if (sih->ccrev < 16)
2436                 return 0xffffffff;
2437
2438         return si_corereg(sih, SI_CC_IDX,
2439                            OFFSETOF(chipcregs_t, gpiotimerval), mask,
2440                            gpiotimerval);
2441 }
2442
2443 uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2444 {
2445         si_info_t *sii;
2446         uint offs;
2447
2448         sii = SI_INFO(sih);
2449         if (sih->ccrev < 20)
2450                 return 0xffffffff;
2451
2452         offs =
2453             (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
2454              OFFSETOF(chipcregs_t, gpiopullup));
2455         return si_corereg(sih, SI_CC_IDX, offs, mask, val);
2456 }
2457
2458 uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2459 {
2460         si_info_t *sii;
2461         uint offs;
2462
2463         sii = SI_INFO(sih);
2464         if (sih->ccrev < 11)
2465                 return 0xffffffff;
2466
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;
2475
2476         return si_corereg(sih, SI_CC_IDX, offs, mask, val);
2477 }
2478
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;
2484
2485         ASSERT(event);
2486         ASSERT(cb != NULL);
2487
2488         sii = SI_INFO(sih);
2489         if (sih->ccrev < 11)
2490                 return NULL;
2491
2492         gi = MALLOC(sii->osh, sizeof(gpioh_item_t));
2493         if (gi == NULL)
2494                 return NULL;
2495
2496         bzero(gi, sizeof(gpioh_item_t));
2497         gi->event = event;
2498         gi->handler = cb;
2499         gi->arg = arg;
2500         gi->level = level;
2501
2502         gi->next = sii->gpioh_head;
2503         sii->gpioh_head = gi;
2504
2505         return (void *)(gi);
2506 }
2507
2508 void BCMATTACHFN(si_gpio_handler_unregister) (si_t *sih, void *gpioh)
2509 {
2510         si_info_t *sii;
2511         gpioh_item_t *p, *n;
2512
2513         sii = SI_INFO(sih);
2514         if (sih->ccrev < 11)
2515                 return;
2516
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;
2530                         }
2531                         p = n;
2532                         n = n->next;
2533                 }
2534         }
2535
2536         ASSERT(0);              /* Not found in list */
2537 }
2538
2539 void si_gpio_handler_process(si_t *sih)
2540 {
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);
2546
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);
2551
2552                         if (status & h->event)
2553                                 h->handler(status, h->arg);
2554                 }
2555         }
2556
2557         si_gpioevent(sih, GPIO_REGEVT, edge, edge);     /* clear edge-trigger status */
2558 }
2559
2560 uint32 si_gpio_int_enable(si_t *sih, bool enable)
2561 {
2562         si_info_t *sii;
2563         uint offs;
2564
2565         sii = SI_INFO(sih);
2566         if (sih->ccrev < 11)
2567                 return 0xffffffff;
2568
2569         offs = OFFSETOF(chipcregs_t, intmask);
2570         return si_corereg
2571                 (sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0));
2572 }
2573
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)
2578 {
2579         uint banksize, bankinfo;
2580         uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2581
2582         ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
2583
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;
2589 }
2590
2591 void si_socdevram(si_t *sih, bool set, u8 *enable, u8 *protect)
2592 {
2593         si_info_t *sii;
2594         uint origidx;
2595         uint intr_val = 0;
2596         sbsocramregs_t *regs;
2597         bool wasup;
2598         uint corerev;
2599
2600         sii = SI_INFO(sih);
2601
2602         /* Block ints and save current core */
2603         INTR_OFF(sii, intr_val);
2604         origidx = si_coreidx(sih);
2605
2606         if (!set)
2607                 *enable = *protect = 0;
2608
2609         /* Switch to SOCRAM core */
2610         regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2611         if (!regs)
2612                 goto done;
2613
2614         /* Get info for determining size */
2615         wasup = si_iscoreup(sih);
2616         if (!wasup)
2617                 si_core_reset(sih, 0, 0);
2618
2619         corerev = si_corerev(sih);
2620         if (corerev >= 10) {
2621                 uint32 extcinfo;
2622                 u8 nb;
2623                 u8 i;
2624                 uint32 bankidx, bankinfo;
2625
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);
2646                                 }
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;
2654                                 }
2655                         }
2656                 }
2657         }
2658
2659         /* Return to previous state and core */
2660         if (!wasup)
2661                 si_core_disable(sih, 0);
2662         si_setcoreidx(sih, origidx);
2663
2664  done:
2665         INTR_RESTORE(sii, intr_val);
2666 }
2667
2668 bool si_socdevram_pkg(si_t *sih)
2669 {
2670         if (si_socdevram_size(sih) > 0)
2671                 return TRUE;
2672         else
2673                 return FALSE;
2674 }
2675
2676 uint32 si_socdevram_size(si_t *sih)
2677 {
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;
2685
2686         sii = SI_INFO(sih);
2687
2688         /* Block ints and save current core */
2689         INTR_OFF(sii, intr_val);
2690         origidx = si_coreidx(sih);
2691
2692         /* Switch to SOCRAM core */
2693         regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2694         if (!regs)
2695                 goto done;
2696
2697         /* Get info for determining size */
2698         wasup = si_iscoreup(sih);
2699         if (!wasup)
2700                 si_core_reset(sih, 0, 0);
2701
2702         corerev = si_corerev(sih);
2703         if (corerev >= 10) {
2704                 uint32 extcinfo;
2705                 u8 nb;
2706                 u8 i;
2707
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);
2715         }
2716
2717         /* Return to previous state and core */
2718         if (!wasup)
2719                 si_core_disable(sih, 0);
2720         si_setcoreidx(sih, origidx);
2721
2722  done:
2723         INTR_RESTORE(sii, intr_val);
2724
2725         return memsize;
2726 }
2727
2728 /* Return the RAM size of the SOCRAM core */
2729 uint32 si_socram_size(si_t *sih)
2730 {
2731         si_info_t *sii;
2732         uint origidx;
2733         uint intr_val = 0;
2734
2735         sbsocramregs_t *regs;
2736         bool wasup;
2737         uint corerev;
2738         uint32 coreinfo;
2739         uint memsize = 0;
2740
2741         sii = SI_INFO(sih);
2742
2743         /* Block ints and save current core */
2744         INTR_OFF(sii, intr_val);
2745         origidx = si_coreidx(sih);
2746
2747         /* Switch to SOCRAM core */
2748         regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
2749         if (!regs)
2750                 goto done;
2751
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);
2758
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);
2780         }
2781
2782         /* Return to previous state and core */
2783         if (!wasup)
2784                 si_core_disable(sih, 0);
2785         si_setcoreidx(sih, origidx);
2786
2787  done:
2788         INTR_RESTORE(sii, intr_val);
2789
2790         return memsize;
2791 }
2792
2793 void si_chipcontrl_epa4331(si_t *sih, bool on)
2794 {
2795         si_info_t *sii;
2796         chipcregs_t *cc;
2797         uint origidx;
2798         uint32 val;
2799
2800         sii = SI_INFO(sih);
2801         origidx = si_coreidx(sih);
2802
2803         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2804
2805         val = R_REG(sii->osh, &cc->chipcontrol);
2806
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));
2817                 }
2818         } else {
2819                 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2820                 W_REG(sii->osh, &cc->chipcontrol, val);
2821         }
2822
2823         si_setcoreidx(sih, origidx);
2824 }
2825
2826 /* Enable BT-COEX & Ex-PA for 4313 */
2827 void si_epa_4313war(si_t *sih)
2828 {
2829         si_info_t *sii;
2830         chipcregs_t *cc;
2831         uint origidx;
2832
2833         sii = SI_INFO(sih);
2834         origidx = si_coreidx(sih);
2835
2836         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2837
2838         /* EPA Fix */
2839         W_REG(sii->osh, &cc->gpiocontrol,
2840               R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2841
2842         si_setcoreidx(sih, origidx);
2843 }
2844
2845 /* check if the device is removed */
2846 bool si_deviceremoved(si_t *sih)
2847 {
2848         uint32 w;
2849         si_info_t *sii;
2850
2851         sii = SI_INFO(sih);
2852
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;
2860         }
2861         return FALSE;
2862 }
2863
2864 bool si_is_sprom_available(si_t *sih)
2865 {
2866         if (sih->ccrev >= 31) {
2867                 si_info_t *sii;
2868                 uint origidx;
2869                 chipcregs_t *cc;
2870                 uint32 sromctrl;
2871
2872                 if ((sih->cccaps & CC_CAP_SROM) == 0)
2873                         return FALSE;
2874
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;
2881         }
2882
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;
2898         }
2899 }
2900
2901 bool si_is_otp_disabled(si_t *sih)
2902 {
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;
2926         }
2927 }
2928
2929 bool si_is_otp_powered(si_t *sih)
2930 {
2931         if (PMUCTL_ENAB(sih))
2932                 return si_pmu_is_otp_powered(sih, si_osh(sih));
2933         return TRUE;
2934 }
2935
2936 void si_otp_power(si_t *sih, bool on)
2937 {
2938         if (PMUCTL_ENAB(sih))
2939                 si_pmu_otp_power(sih, si_osh(sih), on);
2940         OSL_DELAY(1000);
2941 }
2942
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
2949 {
2950
2951         return TRUE;
2952 }
2953
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
2960 {
2961         if (PMUCTL_ENAB(sih))
2962                 si_pmu_sprom_enable(sih, si_osh(sih), enable);
2963 }
2964
2965 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
2966 int si_cis_source(si_t *sih)
2967 {
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 };
2973
2974         /* PCI chips use SROM format instead of CIS */
2975         if (BUSTYPE(sih->bustype) == PCI_BUS)
2976                 return BCME_NOTFOUND;
2977
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]);
2989                 }
2990
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];
3004                 }
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;
3011                 }
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;
3018                 }
3019         default:
3020                 return CIS_DEFAULT;
3021         }
3022 }