staging: brcm80211: fix "ERROR: open brace '{' following function dec..."
[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 <bcmutils.h>
21 #include <siutils.h>
22 #include <bcmdevs.h>
23 #include <hndsoc.h>
24 #include <sbchipc.h>
25 #include <pci_core.h>
26 #include <pcie_core.h>
27 #include <nicpci.h>
28 #include <bcmnvram.h>
29 #include <bcmsrom.h>
30 #include <hndtcam.h>
31 #include <pcicfg.h>
32 #include <sbsocram.h>
33 #ifdef BCMSDIO
34 #include <bcmsdh.h>
35 #include <sdio.h>
36 #include <sbsdio.h>
37 #include <sbhnddma.h>
38 #include <sbsdpcmdev.h>
39 #include <bcmsdpcm.h>
40 #endif                          /* BCMSDIO */
41 #include <hndpmu.h>
42
43 /* this file now contains only definitions for sb functions, only necessary
44 *for devices using Sonics backplanes (bcm4329)
45 */
46
47 /* if an amba SDIO device is supported, please further restrict the inclusion
48  * of this file
49  */
50 #ifdef BCMSDIO
51 #include "siutils_priv.h"
52 #endif
53
54 /* local prototypes */
55 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
56                               void *regs, uint bustype, void *sdh, char **vars,
57                               uint *varsz);
58 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
59                             void *sdh);
60 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
61                              uint32 savewin, uint *origidx, void *regs);
62 static void si_nvram_process(si_info_t *sii, char *pvars);
63
64 /* dev path concatenation util */
65 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
66 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
67 static bool si_ispcie(si_info_t *sii);
68 static uint BCMINITFN(socram_banksize) (si_info_t *sii, sbsocramregs_t *r,
69                                         uint8 idx, uint8 mtype);
70
71 /* global variable to indicate reservation/release of gpio's */
72 static uint32 si_gpioreservation = 0;
73
74 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
75
76 /*
77  * Allocate a si handle.
78  * devid - pci device id (used to determine chip#)
79  * osh - opaque OS handle
80  * regs - virtual address of initial core registers
81  * bustype - pci/sb/sdio/etc
82  * vars - pointer to a pointer area for "environment" variables
83  * varsz - pointer to int to return the size of the vars
84  */
85 si_t *BCMATTACHFN(si_attach) (uint devid, osl_t *osh, void *regs,
86                               uint bustype, void *sdh, char **vars,
87                               uint *varsz) {
88         si_info_t *sii;
89
90         /* alloc si_info_t */
91         if ((sii = MALLOC(osh, sizeof(si_info_t))) == NULL) {
92                 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n",
93                           MALLOCED(osh)));
94                 return (NULL);
95         }
96
97         if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
98             NULL) {
99                 MFREE(osh, sii, sizeof(si_info_t));
100                 return (NULL);
101         }
102         sii->vars = vars ? *vars : NULL;
103         sii->varsz = varsz ? *varsz : 0;
104
105         return (si_t *) sii;
106 }
107
108 /* global kernel resource */
109 static si_info_t ksii;
110
111 static uint32 wd_msticks;       /* watchdog timer ticks normalized to ms */
112
113 static bool
114 BCMATTACHFN(si_buscore_prep) (si_info_t *sii, uint bustype, uint devid,
115                               void *sdh) {
116
117         /* kludge to enable the clock on the 4306 which lacks a slowclock */
118         if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
119                 si_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
120
121 #if defined(BCMSDIO)
122         if (BUSTYPE(bustype) == SDIO_BUS) {
123                 int err;
124                 uint8 clkset;
125
126                 /* Try forcing SDIO core to do ALPAvail request only */
127                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
128                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
129                                  clkset, &err);
130                 if (!err) {
131                         uint8 clkval;
132
133                         /* If register supported, wait for ALPAvail and then force ALP */
134                         clkval =
135                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
136                                             SBSDIO_FUNC1_CHIPCLKCSR, NULL);
137                         if ((clkval & ~SBSDIO_AVBITS) == clkset) {
138                                 SPINWAIT(((clkval =
139                                            bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
140                                                            SBSDIO_FUNC1_CHIPCLKCSR,
141                                                            NULL)),
142                                           !SBSDIO_ALPAV(clkval)),
143                                          PMU_MAX_TRANSITION_DLY);
144                                 if (!SBSDIO_ALPAV(clkval)) {
145                                         SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval));
146                                         return FALSE;
147                                 }
148                                 clkset =
149                                     SBSDIO_FORCE_HW_CLKREQ_OFF |
150                                     SBSDIO_FORCE_ALP;
151                                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
152                                                  SBSDIO_FUNC1_CHIPCLKCSR,
153                                                  clkset, &err);
154                                 OSL_DELAY(65);
155                         }
156                 }
157
158                 /* Also, disable the extra SDIO pull-ups */
159                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
160                                  NULL);
161         }
162 #endif                          /* defined(BCMSDIO) */
163
164         return TRUE;
165 }
166
167 static bool
168 BCMATTACHFN(si_buscore_setup) (si_info_t *sii, chipcregs_t *cc, uint bustype,
169                                uint32 savewin, uint *origidx, void *regs) {
170         bool pci, pcie;
171         uint i;
172         uint pciidx, pcieidx, pcirev, pcierev;
173
174         cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
175         ASSERT((uintptr) cc);
176
177         /* get chipcommon rev */
178         sii->pub.ccrev = (int)si_corerev(&sii->pub);
179
180         /* get chipcommon chipstatus */
181         if (sii->pub.ccrev >= 11)
182                 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
183
184         /* get chipcommon capabilites */
185         sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
186         /* get chipcommon extended capabilities */
187
188         if (sii->pub.ccrev >= 35)
189                 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
190
191         /* get pmu rev and caps */
192         if (sii->pub.cccaps & CC_CAP_PMU) {
193                 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
194                 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
195         }
196
197         /*
198            SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
199            sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
200            sii->pub.pmucaps));
201          */
202
203         /* figure out bus/orignal core idx */
204         sii->pub.buscoretype = NODEV_CORE_ID;
205         sii->pub.buscorerev = NOREV;
206         sii->pub.buscoreidx = BADIDX;
207
208         pci = pcie = FALSE;
209         pcirev = pcierev = NOREV;
210         pciidx = pcieidx = BADIDX;
211
212         for (i = 0; i < sii->numcores; i++) {
213                 uint cid, crev;
214
215                 si_setcoreidx(&sii->pub, i);
216                 cid = si_coreid(&sii->pub);
217                 crev = si_corerev(&sii->pub);
218
219                 /* Display cores found */
220                 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
221                          i, cid, crev, sii->coresba[i], sii->regs[i]));
222
223                 if (BUSTYPE(bustype) == PCI_BUS) {
224                         if (cid == PCI_CORE_ID) {
225                                 pciidx = i;
226                                 pcirev = crev;
227                                 pci = TRUE;
228                         } else if (cid == PCIE_CORE_ID) {
229                                 pcieidx = i;
230                                 pcierev = crev;
231                                 pcie = TRUE;
232                         }
233                 }
234 #ifdef BCMSDIO
235                 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
236                           (BUSTYPE(bustype) == SPI_BUS)) &&
237                          ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) {
238                         sii->pub.buscorerev = crev;
239                         sii->pub.buscoretype = cid;
240                         sii->pub.buscoreidx = i;
241                 }
242 #endif                          /* BCMSDIO */
243
244                 /* find the core idx before entering this func. */
245                 if ((savewin && (savewin == sii->coresba[i])) ||
246                     (regs == sii->regs[i]))
247                         *origidx = i;
248         }
249
250         if (pci && pcie) {
251                 if (si_ispcie(sii))
252                         pci = FALSE;
253                 else
254                         pcie = FALSE;
255         }
256         if (pci) {
257                 sii->pub.buscoretype = PCI_CORE_ID;
258                 sii->pub.buscorerev = pcirev;
259                 sii->pub.buscoreidx = pciidx;
260         } else if (pcie) {
261                 sii->pub.buscoretype = PCIE_CORE_ID;
262                 sii->pub.buscorerev = pcierev;
263                 sii->pub.buscoreidx = pcieidx;
264         }
265
266         SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
267                  sii->pub.buscoretype, sii->pub.buscorerev));
268
269         /* fixup necessary chip/core configurations */
270         if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
271                 if (SI_FAST(sii)) {
272                         if (!sii->pch &&
273                             ((sii->pch =
274                               (void *)(uintptr) pcicore_init(&sii->pub,
275                                                              sii->osh,
276                                                              (void *)
277                                                              PCIEREGS(sii))) ==
278                              NULL))
279                                 return FALSE;
280                 }
281                 if (si_pci_fixcfg(&sii->pub)) {
282                         SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
283                         return FALSE;
284                 }
285         }
286
287         /* return to the original core */
288         si_setcoreidx(&sii->pub, *origidx);
289
290         return TRUE;
291 }
292
293 static void BCMATTACHFN(si_nvram_process) (si_info_t *sii, char *pvars)
294 {
295         uint w = 0;
296
297         /* get boardtype and boardrev */
298         switch (BUSTYPE(sii->pub.bustype)) {
299         case PCI_BUS:
300                 /* do a pci config read to get subsystem id and subvendor id */
301                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
302                 /* Let nvram variables override subsystem Vend/ID */
303                 if ((sii->pub.boardvendor =
304                      (uint16) si_getdevpathintvar(&sii->pub, "boardvendor"))
305                     == 0)
306                         sii->pub.boardvendor = w & 0xffff;
307                 else
308                         SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii->pub.boardvendor, w & 0xffff));
309                 if ((sii->pub.boardtype =
310                      (uint16) si_getdevpathintvar(&sii->pub, "boardtype"))
311                     == 0)
312                         sii->pub.boardtype = (w >> 16) & 0xffff;
313                 else
314                         SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii->pub.boardtype, (w >> 16) & 0xffff));
315                 break;
316
317 #ifdef BCMSDIO
318         case SDIO_BUS:
319 #endif
320                 sii->pub.boardvendor = getintvar(pvars, "manfid");
321                 sii->pub.boardtype = getintvar(pvars, "prodid");
322                 break;
323
324 #ifdef BCMSDIO
325         case SPI_BUS:
326                 sii->pub.boardvendor = VENDOR_BROADCOM;
327                 sii->pub.boardtype = SPI_BOARD;
328                 break;
329 #endif
330
331         case SI_BUS:
332         case JTAG_BUS:
333                 sii->pub.boardvendor = VENDOR_BROADCOM;
334                 if (pvars == NULL
335                     || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
336                         if ((sii->pub.boardtype =
337                              getintvar(NULL, "boardtype")) == 0)
338                                 sii->pub.boardtype = 0xffff;
339                 break;
340         }
341
342         if (sii->pub.boardtype == 0) {
343                 SI_ERROR(("si_doattach: unknown board type\n"));
344                 ASSERT(sii->pub.boardtype);
345         }
346
347         sii->pub.boardflags = getintvar(pvars, "boardflags");
348 }
349
350 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
351 /* this has been customized for the bcm 4329 ONLY */
352 #ifdef BCMSDIO
353 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
354                                             osl_t *osh, void *regs,
355                                             uint bustype, void *sdh,
356                                             char **vars, uint *varsz) {
357         struct si_pub *sih = &sii->pub;
358         uint32 w, savewin;
359         chipcregs_t *cc;
360         char *pvars = NULL;
361         uint origidx;
362
363         ASSERT(GOODREGS(regs));
364
365         bzero((uchar *) sii, sizeof(si_info_t));
366
367         savewin = 0;
368
369         sih->buscoreidx = BADIDX;
370
371         sii->curmap = regs;
372         sii->sdh = sdh;
373         sii->osh = osh;
374
375         /* find Chipcommon address */
376         cc = (chipcregs_t *) sii->curmap;
377         sih->bustype = bustype;
378
379         if (bustype != BUSTYPE(bustype)) {
380                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
381                 return NULL;
382         }
383
384         /* bus/core/clk setup for register access */
385         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
386                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
387                           bustype));
388                 return NULL;
389         }
390
391         /* ChipID recognition.
392          *   We assume we can read chipid at offset 0 from the regs arg.
393          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
394          *   some way of recognizing them needs to be added here.
395          */
396         w = R_REG(osh, &cc->chipid);
397         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
398         /* Might as wll fill in chip id rev & pkg */
399         sih->chip = w & CID_ID_MASK;
400         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
401         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
402
403         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
404             (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
405                 sih->chippkg = BCM4329_182PIN_PKG_ID;
406         }
407         sih->issim = IS_SIM(sih->chippkg);
408
409         /* scan for cores */
410         /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
411         sb_scan(&sii->pub, regs, devid);
412
413         /* no cores found, bail out */
414         if (sii->numcores == 0) {
415                 SI_ERROR(("si_doattach: could not find any cores\n"));
416                 return NULL;
417         }
418         /* bus/core/clk setup */
419         origidx = SI_CC_IDX;
420         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
421                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
422                 goto exit;
423         }
424
425         /* Init nvram from flash if it exists */
426         nvram_init((void *)&(sii->pub));
427
428         /* Init nvram from sprom/otp if they exist */
429         if (srom_var_init
430             (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
431                 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
432                 goto exit;
433         }
434         pvars = vars ? *vars : NULL;
435         si_nvram_process(sii, pvars);
436
437         /* === NVRAM, clock is ready === */
438
439         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
440         W_REG(osh, &cc->gpiopullup, 0);
441         W_REG(osh, &cc->gpiopulldown, 0);
442         sb_setcoreidx(sih, origidx);
443
444         /* PMU specific initializations */
445         if (PMUCTL_ENAB(sih)) {
446                 uint32 xtalfreq;
447                 si_pmu_init(sih, sii->osh);
448                 si_pmu_chip_init(sih, sii->osh);
449                 xtalfreq = getintvar(pvars, "xtalfreq");
450                 /* If xtalfreq var not available, try to measure it */
451                 if (xtalfreq == 0)
452                         xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
453                 si_pmu_pll_init(sih, sii->osh, xtalfreq);
454                 si_pmu_res_init(sih, sii->osh);
455                 si_pmu_swreg_init(sih, sii->osh);
456         }
457
458         /* setup the GPIO based LED powersave register */
459         if ((w = getintvar(pvars, "leddc")) == 0)
460                 w = DEFAULT_GPIOTIMERVAL;
461         sb_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
462
463 #ifdef BCMDBG
464         /* clear any previous epidiag-induced target abort */
465         sb_taclear(sih, FALSE);
466 #endif                          /* BCMDBG */
467
468         return (sii);
469
470  exit:
471         return NULL;
472 }
473
474 #else                           /* BCMSDIO */
475 static si_info_t *BCMATTACHFN(si_doattach) (si_info_t *sii, uint devid,
476                                             osl_t *osh, void *regs,
477                                             uint bustype, void *sdh,
478                                             char **vars, uint *varsz) {
479         struct si_pub *sih = &sii->pub;
480         uint32 w, savewin;
481         chipcregs_t *cc;
482         char *pvars = NULL;
483         uint origidx;
484
485         ASSERT(GOODREGS(regs));
486
487         bzero((uchar *) sii, sizeof(si_info_t));
488
489         savewin = 0;
490
491         sih->buscoreidx = BADIDX;
492
493         sii->curmap = regs;
494         sii->sdh = sdh;
495         sii->osh = osh;
496
497         /* check to see if we are a si core mimic'ing a pci core */
498         if ((bustype == PCI_BUS) &&
499             (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) ==
500              0xffffffff)) {
501                 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " "devid:0x%x\n", __func__, devid));
502                 bustype = SI_BUS;
503         }
504
505         /* find Chipcommon address */
506         if (bustype == PCI_BUS) {
507                 savewin =
508                     OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
509                 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
510                         savewin = SI_ENUM_BASE;
511                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
512                 cc = (chipcregs_t *) regs;
513         } else {
514                 cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
515         }
516
517         sih->bustype = bustype;
518         if (bustype != BUSTYPE(bustype)) {
519                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
520                 return NULL;
521         }
522
523         /* bus/core/clk setup for register access */
524         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
525                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
526                           bustype));
527                 return NULL;
528         }
529
530         /* ChipID recognition.
531          *   We assume we can read chipid at offset 0 from the regs arg.
532          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
533          *   some way of recognizing them needs to be added here.
534          */
535         w = R_REG(osh, &cc->chipid);
536         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
537         /* Might as wll fill in chip id rev & pkg */
538         sih->chip = w & CID_ID_MASK;
539         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
540         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
541
542         sih->issim = IS_SIM(sih->chippkg);
543
544         /* scan for cores */
545         if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
546                 SI_MSG(("Found chip type AI (0x%08x)\n", w));
547                 /* pass chipc address instead of original core base */
548                 ai_scan(&sii->pub, (void *)(uintptr) cc, devid);
549         } else {
550                 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
551                 return NULL;
552         }
553         /* no cores found, bail out */
554         if (sii->numcores == 0) {
555                 SI_ERROR(("si_doattach: could not find any cores\n"));
556                 return NULL;
557         }
558         /* bus/core/clk setup */
559         origidx = SI_CC_IDX;
560         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
561                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
562                 goto exit;
563         }
564
565         /* assume current core is CC */
566         if ((sii->pub.ccrev == 0x25)
567             &&
568             ((CHIPID(sih->chip) == BCM43236_CHIP_ID
569               || CHIPID(sih->chip) == BCM43235_CHIP_ID
570               || CHIPID(sih->chip) == BCM43238_CHIP_ID)
571              && (CHIPREV(sii->pub.chiprev) <= 2))) {
572
573                 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
574                         uint clkdiv;
575                         clkdiv = R_REG(osh, &cc->clkdiv);
576                         /* otp_clk_div is even number, 120/14 < 9mhz */
577                         clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
578                         W_REG(osh, &cc->clkdiv, clkdiv);
579                         SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
580                 }
581                 OSL_DELAY(10);
582         }
583
584         /* Init nvram from flash if it exists */
585         nvram_init((void *)&(sii->pub));
586
587         /* Init nvram from sprom/otp if they exist */
588         if (srom_var_init
589             (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
590                 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
591                 goto exit;
592         }
593         pvars = vars ? *vars : NULL;
594         si_nvram_process(sii, pvars);
595
596         /* === NVRAM, clock is ready === */
597         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
598         W_REG(osh, &cc->gpiopullup, 0);
599         W_REG(osh, &cc->gpiopulldown, 0);
600         si_setcoreidx(sih, origidx);
601
602         /* PMU specific initializations */
603         if (PMUCTL_ENAB(sih)) {
604                 uint32 xtalfreq;
605                 si_pmu_init(sih, sii->osh);
606                 si_pmu_chip_init(sih, sii->osh);
607                 xtalfreq = getintvar(pvars, "xtalfreq");
608                 /* If xtalfreq var not available, try to measure it */
609                 if (xtalfreq == 0)
610                         xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
611                 si_pmu_pll_init(sih, sii->osh, xtalfreq);
612                 si_pmu_res_init(sih, sii->osh);
613                 si_pmu_swreg_init(sih, sii->osh);
614         }
615
616         /* setup the GPIO based LED powersave register */
617         if ((w = getintvar(pvars, "leddc")) == 0)
618                 w = DEFAULT_GPIOTIMERVAL;
619         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
620
621         if (PCIE(sii)) {
622                 ASSERT(sii->pch != NULL);
623                 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
624         }
625
626         if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
627             (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
628                 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
629                 if (CHIPREV(sih->chiprev) == 0) {
630                         SI_MSG(("Applying 43224A0 WARs\n"));
631                         si_corereg(sih, SI_CC_IDX,
632                                    OFFSETOF(chipcregs_t, chipcontrol),
633                                    CCTRL43224_GPIO_TOGGLE,
634                                    CCTRL43224_GPIO_TOGGLE);
635                         si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
636                                            CCTRL_43224A0_12MA_LED_DRIVE);
637                 }
638                 if (CHIPREV(sih->chiprev) >= 1) {
639                         SI_MSG(("Applying 43224B0+ WARs\n"));
640                         si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
641                                            CCTRL_43224B0_12MA_LED_DRIVE);
642                 }
643         }
644
645         if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
646                 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
647                 SI_MSG(("Applying 4313 WARs\n"));
648                 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
649                                    CCTRL_4313_12MA_LED_DRIVE);
650         }
651
652         if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
653                 /* Enable Ext PA lines depending on chip package option */
654                 si_chipcontrl_epa4331(sih, TRUE);
655         }
656
657         return (sii);
658  exit:
659         if (BUSTYPE(sih->bustype) == PCI_BUS) {
660                 if (sii->pch)
661                         pcicore_deinit(sii->pch);
662                 sii->pch = NULL;
663         }
664
665         return NULL;
666 }
667 #endif                          /* BCMSDIO */
668
669 /* may be called with core in reset */
670 void BCMATTACHFN(si_detach) (si_t *sih)
671 {
672         si_info_t *sii;
673         uint idx;
674
675         struct si_pub *si_local = NULL;
676         bcopy(&sih, &si_local, sizeof(si_t **));
677
678         sii = SI_INFO(sih);
679
680         if (sii == NULL)
681                 return;
682
683         if (BUSTYPE(sih->bustype) == SI_BUS)
684                 for (idx = 0; idx < SI_MAXCORES; idx++)
685                         if (sii->regs[idx]) {
686                                 REG_UNMAP(sii->regs[idx]);
687                                 sii->regs[idx] = NULL;
688                         }
689
690         nvram_exit((void *)si_local);   /* free up nvram buffers */
691
692         if (BUSTYPE(sih->bustype) == PCI_BUS) {
693                 if (sii->pch)
694                         pcicore_deinit(sii->pch);
695                 sii->pch = NULL;
696         }
697 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
698         if (sii != &ksii)
699 #endif                          /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
700                 MFREE(sii->osh, sii, sizeof(si_info_t));
701 }
702
703 void *si_osh(si_t *sih)
704 {
705         si_info_t *sii;
706
707         sii = SI_INFO(sih);
708         return sii->osh;
709 }
710
711 void si_setosh(si_t *sih, osl_t *osh)
712 {
713         si_info_t *sii;
714
715         sii = SI_INFO(sih);
716         if (sii->osh != NULL) {
717                 SI_ERROR(("osh is already set....\n"));
718                 ASSERT(!sii->osh);
719         }
720         sii->osh = osh;
721 }
722
723 /* register driver interrupt disabling and restoring callback functions */
724 void
725 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
726                           void *intrsenabled_fn, void *intr_arg)
727 {
728         si_info_t *sii;
729
730         sii = SI_INFO(sih);
731         sii->intr_arg = intr_arg;
732         sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
733         sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
734         sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
735         /* save current core id.  when this function called, the current core
736          * must be the core which provides driver functions(il, et, wl, etc.)
737          */
738         sii->dev_coreid = sii->coreid[sii->curidx];
739 }
740
741 void si_deregister_intr_callback(si_t *sih)
742 {
743         si_info_t *sii;
744
745         sii = SI_INFO(sih);
746         sii->intrsoff_fn = NULL;
747 }
748
749 uint si_intflag(si_t *sih)
750 {
751         si_info_t *sii = SI_INFO(sih);
752
753         if (CHIPTYPE(sih->socitype) == SOCI_AI)
754                 return R_REG(sii->osh,
755                              ((uint32 *) (uintptr) (sii->oob_router +
756                                                     OOB_STATUSA)));
757         else {
758                 ASSERT(0);
759                 return 0;
760         }
761 }
762
763 uint si_flag(si_t *sih)
764 {
765         if (CHIPTYPE(sih->socitype) == SOCI_AI)
766                 return ai_flag(sih);
767         else {
768                 ASSERT(0);
769                 return 0;
770         }
771 }
772
773 void si_setint(si_t *sih, int siflag)
774 {
775         if (CHIPTYPE(sih->socitype) == SOCI_AI)
776                 ai_setint(sih, siflag);
777         else
778                 ASSERT(0);
779 }
780
781 #ifndef BCMSDIO
782 uint si_coreid(si_t *sih)
783 {
784         si_info_t *sii;
785
786         sii = SI_INFO(sih);
787         return sii->coreid[sii->curidx];
788 }
789 #endif
790
791 uint si_coreidx(si_t *sih)
792 {
793         si_info_t *sii;
794
795         sii = SI_INFO(sih);
796         return sii->curidx;
797 }
798
799 /* return the core-type instantiation # of the current core */
800 uint si_coreunit(si_t *sih)
801 {
802         si_info_t *sii;
803         uint idx;
804         uint coreid;
805         uint coreunit;
806         uint i;
807
808         sii = SI_INFO(sih);
809         coreunit = 0;
810
811         idx = sii->curidx;
812
813         ASSERT(GOODREGS(sii->curmap));
814         coreid = si_coreid(sih);
815
816         /* count the cores of our type */
817         for (i = 0; i < idx; i++)
818                 if (sii->coreid[i] == coreid)
819                         coreunit++;
820
821         return (coreunit);
822 }
823
824 uint si_corevendor(si_t *sih)
825 {
826         if (CHIPTYPE(sih->socitype) == SOCI_AI)
827                 return ai_corevendor(sih);
828         else {
829                 ASSERT(0);
830                 return 0;
831         }
832 }
833
834 bool si_backplane64(si_t *sih)
835 {
836         return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
837 }
838
839 #ifndef BCMSDIO
840 uint si_corerev(si_t *sih)
841 {
842         if (CHIPTYPE(sih->socitype) == SOCI_AI)
843                 return ai_corerev(sih);
844         else {
845                 ASSERT(0);
846                 return 0;
847         }
848 }
849 #endif
850
851 /* return index of coreid or BADIDX if not found */
852 uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
853 {
854         si_info_t *sii;
855         uint found;
856         uint i;
857
858         sii = SI_INFO(sih);
859
860         found = 0;
861
862         for (i = 0; i < sii->numcores; i++)
863                 if (sii->coreid[i] == coreid) {
864                         if (found == coreunit)
865                                 return (i);
866                         found++;
867                 }
868
869         return (BADIDX);
870 }
871
872 /* return list of found cores */
873 uint si_corelist(si_t *sih, uint coreid[])
874 {
875         si_info_t *sii;
876
877         sii = SI_INFO(sih);
878
879         bcopy((uchar *) sii->coreid, (uchar *) coreid,
880               (sii->numcores * sizeof(uint)));
881         return (sii->numcores);
882 }
883
884 /* return current register mapping */
885 void *si_coreregs(si_t *sih)
886 {
887         si_info_t *sii;
888
889         sii = SI_INFO(sih);
890         ASSERT(GOODREGS(sii->curmap));
891
892         return (sii->curmap);
893 }
894
895 /*
896  * This function changes logical "focus" to the indicated core;
897  * must be called with interrupts off.
898  * Moreover, callers should keep interrupts off during switching out of and back to d11 core
899  */
900 void *si_setcore(si_t *sih, uint coreid, uint coreunit)
901 {
902         uint idx;
903
904         idx = si_findcoreidx(sih, coreid, coreunit);
905         if (!GOODIDX(idx))
906                 return (NULL);
907
908         if (CHIPTYPE(sih->socitype) == SOCI_AI)
909                 return ai_setcoreidx(sih, idx);
910         else {
911 #ifdef BCMSDIO
912                 return sb_setcoreidx(sih, idx);
913 #else
914                 ASSERT(0);
915                 return NULL;
916 #endif
917         }
918 }
919
920 #ifndef BCMSDIO
921 void *si_setcoreidx(si_t *sih, uint coreidx)
922 {
923         if (CHIPTYPE(sih->socitype) == SOCI_AI)
924                 return ai_setcoreidx(sih, coreidx);
925         else {
926                 ASSERT(0);
927                 return NULL;
928         }
929 }
930 #endif
931
932 /* Turn off interrupt as required by sb_setcore, before switch core */
933 void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
934 {
935         void *cc;
936         si_info_t *sii;
937
938         sii = SI_INFO(sih);
939
940         if (SI_FAST(sii)) {
941                 /* Overloading the origidx variable to remember the coreid,
942                  * this works because the core ids cannot be confused with
943                  * core indices.
944                  */
945                 *origidx = coreid;
946                 if (coreid == CC_CORE_ID)
947                         return (void *)CCREGS_FAST(sii);
948                 else if (coreid == sih->buscoretype)
949                         return (void *)PCIEREGS(sii);
950         }
951         INTR_OFF(sii, *intr_val);
952         *origidx = sii->curidx;
953         cc = si_setcore(sih, coreid, 0);
954         ASSERT(cc != NULL);
955
956         return cc;
957 }
958
959 /* restore coreidx and restore interrupt */
960 void si_restore_core(si_t *sih, uint coreid, uint intr_val)
961 {
962         si_info_t *sii;
963
964         sii = SI_INFO(sih);
965         if (SI_FAST(sii)
966             && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
967                 return;
968
969         si_setcoreidx(sih, coreid);
970         INTR_RESTORE(sii, intr_val);
971 }
972
973 int si_numaddrspaces(si_t *sih)
974 {
975         if (CHIPTYPE(sih->socitype) == SOCI_AI)
976                 return ai_numaddrspaces(sih);
977         else {
978                 ASSERT(0);
979                 return 0;
980         }
981 }
982
983 uint32 si_addrspace(si_t *sih, uint asidx)
984 {
985         if (CHIPTYPE(sih->socitype) == SOCI_AI)
986                 return ai_addrspace(sih, asidx);
987         else {
988                 ASSERT(0);
989                 return 0;
990         }
991 }
992
993 uint32 si_addrspacesize(si_t *sih, uint asidx)
994 {
995         if (CHIPTYPE(sih->socitype) == SOCI_AI)
996                 return ai_addrspacesize(sih, asidx);
997         else {
998                 ASSERT(0);
999                 return 0;
1000         }
1001 }
1002
1003 uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1004 {
1005         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1006                 return ai_core_cflags(sih, mask, val);
1007         else {
1008                 ASSERT(0);
1009                 return 0;
1010         }
1011 }
1012
1013 void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1014 {
1015         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1016                 ai_core_cflags_wo(sih, mask, val);
1017         else
1018                 ASSERT(0);
1019 }
1020
1021 uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1022 {
1023         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1024                 return ai_core_sflags(sih, mask, val);
1025         else {
1026                 ASSERT(0);
1027                 return 0;
1028         }
1029 }
1030
1031 bool si_iscoreup(si_t *sih)
1032 {
1033         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1034                 return ai_iscoreup(sih);
1035         else {
1036 #ifdef BCMSDIO
1037                 return sb_iscoreup(sih);
1038 #else
1039                 ASSERT(0);
1040                 return FALSE;
1041 #endif
1042         }
1043 }
1044
1045 void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1046 {
1047         /* only for 4319, no requirement for SOCI_SB */
1048         if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1049                 ai_write_wrap_reg(sih, offset, val);
1050         }
1051 }
1052
1053 uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1054 {
1055
1056         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1057                 return ai_corereg(sih, coreidx, regoff, mask, val);
1058         else {
1059 #ifdef BCMSDIO
1060                 return sb_corereg(sih, coreidx, regoff, mask, val);
1061 #else
1062                 ASSERT(0);
1063                 return 0;
1064 #endif
1065         }
1066 }
1067
1068 void si_core_disable(si_t *sih, uint32 bits)
1069 {
1070
1071         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1072                 ai_core_disable(sih, bits);
1073 #ifdef BCMSDIO
1074         else
1075                 sb_core_disable(sih, bits);
1076 #endif
1077 }
1078
1079 void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1080 {
1081         if (CHIPTYPE(sih->socitype) == SOCI_AI)
1082                 ai_core_reset(sih, bits, resetbits);
1083 #ifdef BCMSDIO
1084         else
1085                 sb_core_reset(sih, bits, resetbits);
1086 #endif
1087 }
1088
1089 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1090 int si_corebist(si_t *sih)
1091 {
1092         uint32 cflags;
1093         int result = 0;
1094
1095         /* Read core control flags */
1096         cflags = si_core_cflags(sih, 0, 0);
1097
1098         /* Set bist & fgc */
1099         si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1100
1101         /* Wait for bist done */
1102         SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1103
1104         if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1105                 result = BCME_ERROR;
1106
1107         /* Reset core control flags */
1108         si_core_cflags(sih, 0xffff, cflags);
1109
1110         return result;
1111 }
1112
1113 static uint32 BCMINITFN(factor6) (uint32 x)
1114 {
1115         switch (x) {
1116         case CC_F6_2:
1117                 return 2;
1118         case CC_F6_3:
1119                 return 3;
1120         case CC_F6_4:
1121                 return 4;
1122         case CC_F6_5:
1123                 return 5;
1124         case CC_F6_6:
1125                 return 6;
1126         case CC_F6_7:
1127                 return 7;
1128         default:
1129                 return 0;
1130         }
1131 }
1132
1133 /* calculate the speed the SI would run at given a set of clockcontrol values */
1134 uint32 BCMINITFN(si_clock_rate) (uint32 pll_type, uint32 n, uint32 m)
1135 {
1136         uint32 n1, n2, clock, m1, m2, m3, mc;
1137
1138         n1 = n & CN_N1_MASK;
1139         n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1140
1141         if (pll_type == PLL_TYPE6) {
1142                 if (m & CC_T6_MMASK)
1143                         return CC_T6_M1;
1144                 else
1145                         return CC_T6_M0;
1146         } else if ((pll_type == PLL_TYPE1) ||
1147                    (pll_type == PLL_TYPE3) ||
1148                    (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1149                 n1 = factor6(n1);
1150                 n2 += CC_F5_BIAS;
1151         } else if (pll_type == PLL_TYPE2) {
1152                 n1 += CC_T2_BIAS;
1153                 n2 += CC_T2_BIAS;
1154                 ASSERT((n1 >= 2) && (n1 <= 7));
1155                 ASSERT((n2 >= 5) && (n2 <= 23));
1156         } else if (pll_type == PLL_TYPE5) {
1157                 return (100000000);
1158         } else
1159                 ASSERT(0);
1160         /* PLL types 3 and 7 use BASE2 (25Mhz) */
1161         if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) {
1162                 clock = CC_CLOCK_BASE2 * n1 * n2;
1163         } else
1164                 clock = CC_CLOCK_BASE1 * n1 * n2;
1165
1166         if (clock == 0)
1167                 return 0;
1168
1169         m1 = m & CC_M1_MASK;
1170         m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1171         m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1172         mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1173
1174         if ((pll_type == PLL_TYPE1) ||
1175             (pll_type == PLL_TYPE3) ||
1176             (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
1177                 m1 = factor6(m1);
1178                 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1179                         m2 += CC_F5_BIAS;
1180                 else
1181                         m2 = factor6(m2);
1182                 m3 = factor6(m3);
1183
1184                 switch (mc) {
1185                 case CC_MC_BYPASS:
1186                         return (clock);
1187                 case CC_MC_M1:
1188                         return (clock / m1);
1189                 case CC_MC_M1M2:
1190                         return (clock / (m1 * m2));
1191                 case CC_MC_M1M2M3:
1192                         return (clock / (m1 * m2 * m3));
1193                 case CC_MC_M1M3:
1194                         return (clock / (m1 * m3));
1195                 default:
1196                         return (0);
1197                 }
1198         } else {
1199                 ASSERT(pll_type == PLL_TYPE2);
1200
1201                 m1 += CC_T2_BIAS;
1202                 m2 += CC_T2M2_BIAS;
1203                 m3 += CC_T2_BIAS;
1204                 ASSERT((m1 >= 2) && (m1 <= 7));
1205                 ASSERT((m2 >= 3) && (m2 <= 10));
1206                 ASSERT((m3 >= 2) && (m3 <= 7));
1207
1208                 if ((mc & CC_T2MC_M1BYP) == 0)
1209                         clock /= m1;
1210                 if ((mc & CC_T2MC_M2BYP) == 0)
1211                         clock /= m2;
1212                 if ((mc & CC_T2MC_M3BYP) == 0)
1213                         clock /= m3;
1214
1215                 return (clock);
1216         }
1217 }
1218
1219 uint32 BCMINITFN(si_clock) (si_t *sih)
1220 {
1221         si_info_t *sii;
1222         chipcregs_t *cc;
1223         uint32 n, m;
1224         uint idx;
1225         uint32 pll_type, rate;
1226         uint intr_val = 0;
1227
1228         sii = SI_INFO(sih);
1229         INTR_OFF(sii, intr_val);
1230         if (PMUCTL_ENAB(sih)) {
1231                 rate = si_pmu_si_clock(sih, sii->osh);
1232                 goto exit;
1233         }
1234
1235         idx = sii->curidx;
1236         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1237         ASSERT(cc != NULL);
1238
1239         n = R_REG(sii->osh, &cc->clockcontrol_n);
1240         pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1241         if (pll_type == PLL_TYPE6)
1242                 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1243         else if (pll_type == PLL_TYPE3)
1244                 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1245         else
1246                 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1247
1248         /* calculate rate */
1249         rate = si_clock_rate(pll_type, n, m);
1250
1251         if (pll_type == PLL_TYPE3)
1252                 rate = rate / 2;
1253
1254         /* switch back to previous core */
1255         si_setcoreidx(sih, idx);
1256  exit:
1257         INTR_RESTORE(sii, intr_val);
1258
1259         return rate;
1260 }
1261
1262 uint32 BCMINITFN(si_alp_clock) (si_t *sih)
1263 {
1264         if (PMUCTL_ENAB(sih))
1265                 return si_pmu_alp_clock(sih, si_osh(sih));
1266
1267         return ALP_CLOCK;
1268 }
1269
1270 uint32 BCMINITFN(si_ilp_clock) (si_t *sih)
1271 {
1272         if (PMUCTL_ENAB(sih))
1273                 return si_pmu_ilp_clock(sih, si_osh(sih));
1274
1275         return ILP_CLOCK;
1276 }
1277
1278 /* set chip watchdog reset timer to fire in 'ticks' */
1279 void si_watchdog(si_t *sih, uint ticks)
1280 {
1281         uint nb, maxt;
1282
1283         if (PMUCTL_ENAB(sih)) {
1284
1285                 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1286                     (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1287                         si_corereg(sih, SI_CC_IDX,
1288                                    OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1289                         si_setcore(sih, USB20D_CORE_ID, 0);
1290                         si_core_disable(sih, 1);
1291                         si_setcore(sih, CC_CORE_ID, 0);
1292                 }
1293
1294                 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1295                 /* The mips compiler uses the sllv instruction,
1296                  * so we specially handle the 32-bit case.
1297                  */
1298                 if (nb == 32)
1299                         maxt = 0xffffffff;
1300                 else
1301                         maxt = ((1 << nb) - 1);
1302
1303                 if (ticks == 1)
1304                         ticks = 2;
1305                 else if (ticks > maxt)
1306                         ticks = maxt;
1307
1308                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog),
1309                            ~0, ticks);
1310         } else {
1311                 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1312                 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1313                 maxt = (1 << 28) - 1;
1314                 if (ticks > maxt)
1315                         ticks = maxt;
1316
1317                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
1318                            ticks);
1319         }
1320 }
1321
1322 /* trigger watchdog reset after ms milliseconds */
1323 void si_watchdog_ms(si_t *sih, uint32 ms)
1324 {
1325         si_watchdog(sih, wd_msticks * ms);
1326 }
1327
1328 uint16 BCMATTACHFN(si_d11_devid) (si_t *sih)
1329 {
1330         si_info_t *sii = SI_INFO(sih);
1331         uint16 device;
1332
1333         /* normal case: nvram variable with devpath->devid->wl0id */
1334         if ((device = (uint16) si_getdevpathintvar(sih, "devid")) != 0) ;
1335         /* Get devid from OTP/SPROM depending on where the SROM is read */
1336         else if ((device = (uint16) getintvar(sii->vars, "devid")) != 0) ;
1337         /* no longer support wl0id, but keep the code here for backward compatibility. */
1338         else if ((device = (uint16) getintvar(sii->vars, "wl0id")) != 0) ;
1339         else
1340                 /* ignore it */
1341                 device = 0xffff;
1342
1343         return device;
1344 }
1345
1346 /* return the slow clock source - LPO, XTAL, or PCI */
1347 static uint si_slowclk_src(si_info_t *sii)
1348 {
1349         chipcregs_t *cc;
1350
1351         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1352
1353         if (sii->pub.ccrev < 6) {
1354                 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1355                     (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32))
1356                      & PCI_CFG_GPIO_SCS))
1357                         return (SCC_SS_PCI);
1358                 else
1359                         return (SCC_SS_XTAL);
1360         } else if (sii->pub.ccrev < 10) {
1361                 cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
1362                 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1363         } else                  /* Insta-clock */
1364                 return (SCC_SS_XTAL);
1365 }
1366
1367 /* return the ILP (slowclock) min or max frequency */
1368 static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1369 {
1370         uint32 slowclk;
1371         uint div;
1372
1373         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1374
1375         /* shouldn't be here unless we've established the chip has dynamic clk control */
1376         ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1377
1378         slowclk = si_slowclk_src(sii);
1379         if (sii->pub.ccrev < 6) {
1380                 if (slowclk == SCC_SS_PCI)
1381                         return (max_freq ? (PCIMAXFREQ / 64)
1382                                 : (PCIMINFREQ / 64));
1383                 else
1384                         return (max_freq ? (XTALMAXFREQ / 32)
1385                                 : (XTALMINFREQ / 32));
1386         } else if (sii->pub.ccrev < 10) {
1387                 div = 4 *
1388                     (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
1389                       SCC_CD_SHIFT) + 1);
1390                 if (slowclk == SCC_SS_LPO)
1391                         return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1392                 else if (slowclk == SCC_SS_XTAL)
1393                         return (max_freq ? (XTALMAXFREQ / div)
1394                                 : (XTALMINFREQ / div));
1395                 else if (slowclk == SCC_SS_PCI)
1396                         return (max_freq ? (PCIMAXFREQ / div)
1397                                 : (PCIMINFREQ / div));
1398                 else
1399                         ASSERT(0);
1400         } else {
1401                 /* Chipc rev 10 is InstaClock */
1402                 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1403                 div = 4 * (div + 1);
1404                 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1405         }
1406         return (0);
1407 }
1408
1409 static void BCMINITFN(si_clkctl_setdelay) (si_info_t *sii, void *chipcregs)
1410 {
1411         chipcregs_t *cc = (chipcregs_t *) chipcregs;
1412         uint slowmaxfreq, pll_delay, slowclk;
1413         uint pll_on_delay, fref_sel_delay;
1414
1415         pll_delay = PLL_DELAY;
1416
1417         /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1418          * since the xtal will also be powered down by dynamic clk control logic.
1419          */
1420
1421         slowclk = si_slowclk_src(sii);
1422         if (slowclk != SCC_SS_XTAL)
1423                 pll_delay += XTAL_ON_DELAY;
1424
1425         /* Starting with 4318 it is ILP that is used for the delays */
1426         slowmaxfreq =
1427             si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1428
1429         pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1430         fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1431
1432         W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1433         W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1434 }
1435
1436 /* initialize power control delay registers */
1437 void BCMINITFN(si_clkctl_init) (si_t *sih)
1438 {
1439         si_info_t *sii;
1440         uint origidx = 0;
1441         chipcregs_t *cc;
1442         bool fast;
1443
1444         if (!CCCTL_ENAB(sih))
1445                 return;
1446
1447         sii = SI_INFO(sih);
1448         fast = SI_FAST(sii);
1449         if (!fast) {
1450                 origidx = sii->curidx;
1451                 if ((cc =
1452                      (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1453                         return;
1454         } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1455                 return;
1456         ASSERT(cc != NULL);
1457
1458         /* set all Instaclk chip ILP to 1 MHz */
1459         if (sih->ccrev >= 10)
1460                 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1461                         (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1462
1463         si_clkctl_setdelay(sii, (void *)(uintptr) cc);
1464
1465         if (!fast)
1466                 si_setcoreidx(sih, origidx);
1467 }
1468
1469 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1470 uint16 BCMINITFN(si_clkctl_fast_pwrup_delay) (si_t *sih)
1471 {
1472         si_info_t *sii;
1473         uint origidx = 0;
1474         chipcregs_t *cc;
1475         uint slowminfreq;
1476         uint16 fpdelay;
1477         uint intr_val = 0;
1478         bool fast;
1479
1480         sii = SI_INFO(sih);
1481         if (PMUCTL_ENAB(sih)) {
1482                 INTR_OFF(sii, intr_val);
1483                 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1484                 INTR_RESTORE(sii, intr_val);
1485                 return fpdelay;
1486         }
1487
1488         if (!CCCTL_ENAB(sih))
1489                 return 0;
1490
1491         fast = SI_FAST(sii);
1492         fpdelay = 0;
1493         if (!fast) {
1494                 origidx = sii->curidx;
1495                 INTR_OFF(sii, intr_val);
1496                 if ((cc =
1497                      (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1498                         goto done;
1499         } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1500                 goto done;
1501         ASSERT(cc != NULL);
1502
1503         slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1504         fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1505                    (slowminfreq - 1)) / slowminfreq;
1506
1507  done:
1508         if (!fast) {
1509                 si_setcoreidx(sih, origidx);
1510                 INTR_RESTORE(sii, intr_val);
1511         }
1512         return fpdelay;
1513 }
1514
1515 /* turn primary xtal and/or pll off/on */
1516 int si_clkctl_xtal(si_t *sih, uint what, bool on)
1517 {
1518         si_info_t *sii;
1519         uint32 in, out, outen;
1520
1521         sii = SI_INFO(sih);
1522
1523         switch (BUSTYPE(sih->bustype)) {
1524
1525 #ifdef BCMSDIO
1526         case SDIO_BUS:
1527                 return (-1);
1528 #endif                          /* BCMSDIO */
1529
1530         case PCI_BUS:
1531                 /* pcie core doesn't have any mapping to control the xtal pu */
1532                 if (PCIE(sii))
1533                         return -1;
1534
1535                 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
1536                 out =
1537                     OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
1538                 outen =
1539                     OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1540                                         sizeof(uint32));
1541
1542                 /*
1543                  * Avoid glitching the clock if GPRS is already using it.
1544                  * We can't actually read the state of the PLLPD so we infer it
1545                  * by the value of XTAL_PU which *is* readable via gpioin.
1546                  */
1547                 if (on && (in & PCI_CFG_GPIO_XTAL))
1548                         return (0);
1549
1550                 if (what & XTAL)
1551                         outen |= PCI_CFG_GPIO_XTAL;
1552                 if (what & PLL)
1553                         outen |= PCI_CFG_GPIO_PLL;
1554
1555                 if (on) {
1556                         /* turn primary xtal on */
1557                         if (what & XTAL) {
1558                                 out |= PCI_CFG_GPIO_XTAL;
1559                                 if (what & PLL)
1560                                         out |= PCI_CFG_GPIO_PLL;
1561                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1562                                                      sizeof(uint32), out);
1563                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1564                                                      sizeof(uint32), outen);
1565                                 OSL_DELAY(XTAL_ON_DELAY);
1566                         }
1567
1568                         /* turn pll on */
1569                         if (what & PLL) {
1570                                 out &= ~PCI_CFG_GPIO_PLL;
1571                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1572                                                      sizeof(uint32), out);
1573                                 OSL_DELAY(2000);
1574                         }
1575                 } else {
1576                         if (what & XTAL)
1577                                 out &= ~PCI_CFG_GPIO_XTAL;
1578                         if (what & PLL)
1579                                 out |= PCI_CFG_GPIO_PLL;
1580                         OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1581                                              sizeof(uint32), out);
1582                         OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1583                                              sizeof(uint32), outen);
1584                 }
1585
1586         default:
1587                 return (-1);
1588         }
1589
1590         return (0);
1591 }
1592
1593 /*
1594  *  clock control policy function throught chipcommon
1595  *
1596  *    set dynamic clk control mode (forceslow, forcefast, dynamic)
1597  *    returns true if we are forcing fast clock
1598  *    this is a wrapper over the next internal function
1599  *      to allow flexible policy settings for outside caller
1600  */
1601 bool si_clkctl_cc(si_t *sih, uint mode)
1602 {
1603         si_info_t *sii;
1604
1605         sii = SI_INFO(sih);
1606
1607         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1608         if (sih->ccrev < 6)
1609                 return FALSE;
1610
1611         if (PCI_FORCEHT(sii))
1612                 return (mode == CLK_FAST);
1613
1614         return _si_clkctl_cc(sii, mode);
1615 }
1616
1617 /* clk control mechanism through chipcommon, no policy checking */
1618 static bool _si_clkctl_cc(si_info_t *sii, uint mode)
1619 {
1620         uint origidx = 0;
1621         chipcregs_t *cc;
1622         uint32 scc;
1623         uint intr_val = 0;
1624         bool fast = SI_FAST(sii);
1625
1626         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1627         if (sii->pub.ccrev < 6)
1628                 return (FALSE);
1629
1630         /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1631         ASSERT(sii->pub.ccrev != 10);
1632
1633         if (!fast) {
1634                 INTR_OFF(sii, intr_val);
1635                 origidx = sii->curidx;
1636
1637                 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1638                     si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1639                     (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1640                         goto done;
1641
1642                 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
1643         } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1644                 goto done;
1645         ASSERT(cc != NULL);
1646
1647         if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1648                 goto done;
1649
1650         switch (mode) {
1651         case CLK_FAST:          /* FORCEHT, fast (pll) clock */
1652                 if (sii->pub.ccrev < 10) {
1653                         /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1654                         si_clkctl_xtal(&sii->pub, XTAL, ON);
1655                         SET_REG(sii->osh, &cc->slow_clk_ctl,
1656                                 (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1657                 } else if (sii->pub.ccrev < 20) {
1658                         OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1659                 } else {
1660                         OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1661                 }
1662
1663                 /* wait for the PLL */
1664                 if (PMUCTL_ENAB(&sii->pub)) {
1665                         uint32 htavail = CCS_HTAVAIL;
1666                         SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
1667                                   == 0), PMU_MAX_TRANSITION_DLY);
1668                         ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1669                 } else {
1670                         OSL_DELAY(PLL_DELAY);
1671                 }
1672                 break;
1673
1674         case CLK_DYNAMIC:       /* enable dynamic clock control */
1675                 if (sii->pub.ccrev < 10) {
1676                         scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1677                         scc &= ~(SCC_FS | SCC_IP | SCC_XC);
1678                         if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
1679                                 scc |= SCC_XC;
1680                         W_REG(sii->osh, &cc->slow_clk_ctl, scc);
1681
1682                         /* for dynamic control, we have to release our xtal_pu "force on" */
1683                         if (scc & SCC_XC)
1684                                 si_clkctl_xtal(&sii->pub, XTAL, OFF);
1685                 } else if (sii->pub.ccrev < 20) {
1686                         /* Instaclock */
1687                         AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
1688                 } else {
1689                         AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
1690                 }
1691                 break;
1692
1693         default:
1694                 ASSERT(0);
1695         }
1696
1697  done:
1698         if (!fast) {
1699                 si_setcoreidx(&sii->pub, origidx);
1700                 INTR_RESTORE(sii, intr_val);
1701         }
1702         return (mode == CLK_FAST);
1703 }
1704
1705 /* Build device path. Support SI, PCI, and JTAG for now. */
1706 int BCMATTACHFN(si_devpath) (si_t *sih, char *path, int size)
1707 {
1708         int slen;
1709
1710         ASSERT(path != NULL);
1711         ASSERT(size >= SI_DEVPATH_BUFSZ);
1712
1713         if (!path || size <= 0)
1714                 return -1;
1715
1716         switch (BUSTYPE(sih->bustype)) {
1717         case SI_BUS:
1718         case JTAG_BUS:
1719                 slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
1720                 break;
1721         case PCI_BUS:
1722                 ASSERT((SI_INFO(sih))->osh != NULL);
1723                 slen = snprintf(path, (size_t) size, "pci/%u/%u/",
1724                                 OSL_PCI_BUS((SI_INFO(sih))->osh),
1725                                 OSL_PCI_SLOT((SI_INFO(sih))->osh));
1726                 break;
1727
1728 #ifdef BCMSDIO
1729         case SDIO_BUS:
1730                 SI_ERROR(("si_devpath: device 0 assumed\n"));
1731                 slen = snprintf(path, (size_t) size, "sd/%u/", si_coreidx(sih));
1732                 break;
1733 #endif
1734         default:
1735                 slen = -1;
1736                 ASSERT(0);
1737                 break;
1738         }
1739
1740         if (slen < 0 || slen >= size) {
1741                 path[0] = '\0';
1742                 return -1;
1743         }
1744
1745         return 0;
1746 }
1747
1748 /* Get a variable, but only if it has a devpath prefix */
1749 char *BCMATTACHFN(si_getdevpathvar) (si_t *sih, const char *name)
1750 {
1751         char varname[SI_DEVPATH_BUFSZ + 32];
1752
1753         si_devpathvar(sih, varname, sizeof(varname), name);
1754
1755         return (getvar(NULL, varname));
1756 }
1757
1758 /* Get a variable, but only if it has a devpath prefix */
1759 int BCMATTACHFN(si_getdevpathintvar) (si_t *sih, const char *name)
1760 {
1761 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1762         return (getintvar(NULL, name));
1763 #else
1764         char varname[SI_DEVPATH_BUFSZ + 32];
1765
1766         si_devpathvar(sih, varname, sizeof(varname), name);
1767
1768         return (getintvar(NULL, varname));
1769 #endif
1770 }
1771
1772 char *si_getnvramflvar(si_t *sih, const char *name)
1773 {
1774         return (getvar(NULL, name));
1775 }
1776
1777 /* Concatenate the dev path with a varname into the given 'var' buffer
1778  * and return the 'var' pointer.
1779  * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1780  * On overflow, the first char will be set to '\0'.
1781  */
1782 static char *BCMATTACHFN(si_devpathvar) (si_t *sih, char *var, int len,
1783                                          const char *name) {
1784         uint path_len;
1785
1786         if (!var || len <= 0)
1787                 return var;
1788
1789         if (si_devpath(sih, var, len) == 0) {
1790                 path_len = strlen(var);
1791
1792                 if (strlen(name) + 1 > (uint) (len - path_len))
1793                         var[0] = '\0';
1794                 else
1795                         strncpy(var + path_len, name, len - path_len - 1);
1796         }
1797
1798         return var;
1799 }
1800
1801 uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
1802 {
1803         si_info_t *sii;
1804
1805         sii = SI_INFO(sih);
1806
1807         if (!PCIE(sii)) {
1808                 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1809                 return 0;
1810         }
1811
1812         return pcicore_pciereg(sii->pch, offset, mask, val, type);
1813 }
1814
1815 uint32
1816 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask,
1817                  uint32 val)
1818 {
1819         si_info_t *sii;
1820
1821         sii = SI_INFO(sih);
1822
1823         if (!PCIE(sii)) {
1824                 SI_ERROR(("%s: Not a PCIE device\n", __func__));
1825                 return 0;
1826         }
1827
1828         return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
1829
1830 }
1831
1832 /* return TRUE if PCIE capability exists in the pci config space */
1833 static bool si_ispcie(si_info_t *sii)
1834 {
1835         uint8 cap_ptr;
1836
1837         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1838                 return FALSE;
1839
1840         cap_ptr =
1841             pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1842                                         NULL);
1843         if (!cap_ptr)
1844                 return FALSE;
1845
1846         return TRUE;
1847 }
1848
1849 /* Wake-on-wireless-LAN (WOWL) support functions */
1850 /* Enable PME generation and disable clkreq */
1851 void si_pci_pmeen(si_t *sih)
1852 {
1853         si_info_t *sii;
1854
1855         sii = SI_INFO(sih);
1856
1857         pcicore_pmeen(sii->pch);
1858 }
1859
1860 /* Return TRUE if PME status is set */
1861 bool si_pci_pmestat(si_t *sih)
1862 {
1863         si_info_t *sii;
1864
1865         sii = SI_INFO(sih);
1866
1867         return pcicore_pmestat(sii->pch);
1868 }
1869
1870 /* Disable PME generation, clear the PME status bit if set */
1871 void si_pci_pmeclr(si_t *sih)
1872 {
1873         si_info_t *sii;
1874
1875         sii = SI_INFO(sih);
1876
1877         pcicore_pmeclr(sii->pch);
1878 }
1879
1880 #ifdef BCMSDIO
1881 /* initialize the sdio core */
1882 void si_sdio_init(si_t *sih)
1883 {
1884         si_info_t *sii = SI_INFO(sih);
1885
1886         if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1887             (sih->buscoretype == SDIOD_CORE_ID)) {
1888                 uint idx;
1889                 sdpcmd_regs_t *sdpregs;
1890
1891                 /* get the current core index */
1892                 idx = sii->curidx;
1893                 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1894
1895                 /* switch to sdio core */
1896                 if (!
1897                     (sdpregs =
1898                      (sdpcmd_regs_t *) si_setcore(sih, PCMCIA_CORE_ID, 0)))
1899                         sdpregs =
1900                             (sdpcmd_regs_t *) si_setcore(sih, SDIOD_CORE_ID, 0);
1901                 ASSERT(sdpregs);
1902
1903                 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));
1904
1905                 /* enable backplane error and core interrupts */
1906                 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
1907                 W_REG(sii->osh, &sdpregs->sbintmask,
1908                       (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
1909
1910                 /* switch back to previous core */
1911                 si_setcoreidx(sih, idx);
1912         }
1913
1914         /* enable interrupts */
1915         bcmsdh_intr_enable(sii->sdh);
1916
1917 }
1918 #endif                          /* BCMSDIO */
1919
1920 bool BCMATTACHFN(si_pci_war16165) (si_t *sih)
1921 {
1922         si_info_t *sii;
1923
1924         sii = SI_INFO(sih);
1925
1926         return (PCI(sii) && (sih->buscorerev <= 10));
1927 }
1928
1929 /* Disable pcie_war_ovr for some platforms (sigh!)
1930  * This is for boards that have BFL2_PCIEWAR_OVR set
1931  * but are in systems that still want the benefits of ASPM
1932  * Note that this should be done AFTER si_doattach
1933  */
1934 void si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
1935 {
1936         si_info_t *sii;
1937
1938         sii = SI_INFO(sih);
1939
1940         if (!PCIE(sii))
1941                 return;
1942
1943         pcie_war_ovr_aspm_update(sii->pch, aspm);
1944 }
1945
1946 /* back door for other module to override chippkg */
1947 void si_chippkg_set(si_t *sih, uint val)
1948 {
1949         si_info_t *sii;
1950
1951         sii = SI_INFO(sih);
1952
1953         sii->pub.chippkg = val;
1954 }
1955
1956 void BCMINITFN(si_pci_up) (si_t *sih)
1957 {
1958         si_info_t *sii;
1959
1960         sii = SI_INFO(sih);
1961
1962         /* if not pci bus, we're done */
1963         if (BUSTYPE(sih->bustype) != PCI_BUS)
1964                 return;
1965
1966         if (PCI_FORCEHT(sii))
1967                 _si_clkctl_cc(sii, CLK_FAST);
1968
1969         if (PCIE(sii))
1970                 pcicore_up(sii->pch, SI_PCIUP);
1971
1972 }
1973
1974 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
1975 void BCMUNINITFN(si_pci_sleep) (si_t *sih)
1976 {
1977         si_info_t *sii;
1978
1979         sii = SI_INFO(sih);
1980
1981         pcicore_sleep(sii->pch);
1982 }
1983
1984 /* Unconfigure and/or apply various WARs when going down */
1985 void BCMINITFN(si_pci_down) (si_t *sih)
1986 {
1987         si_info_t *sii;
1988
1989         sii = SI_INFO(sih);
1990
1991         /* if not pci bus, we're done */
1992         if (BUSTYPE(sih->bustype) != PCI_BUS)
1993                 return;
1994
1995         /* release FORCEHT since chip is going to "down" state */
1996         if (PCI_FORCEHT(sii))
1997                 _si_clkctl_cc(sii, CLK_DYNAMIC);
1998
1999         pcicore_down(sii->pch, SI_PCIDOWN);
2000 }
2001
2002 /*
2003  * Configure the pci core for pci client (NIC) action
2004  * coremask is the bitvec of cores by index to be enabled.
2005  */
2006 void BCMATTACHFN(si_pci_setup) (si_t *sih, uint coremask)
2007 {
2008         si_info_t *sii;
2009         sbpciregs_t *pciregs = NULL;
2010         uint32 siflag = 0, w;
2011         uint idx = 0;
2012
2013         sii = SI_INFO(sih);
2014
2015         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2016                 return;
2017
2018         ASSERT(PCI(sii) || PCIE(sii));
2019         ASSERT(sii->pub.buscoreidx != BADIDX);
2020
2021         if (PCI(sii)) {
2022                 /* get current core index */
2023                 idx = sii->curidx;
2024
2025                 /* we interrupt on this backplane flag number */
2026                 siflag = si_flag(sih);
2027
2028                 /* switch over to pci core */
2029                 pciregs =
2030                     (sbpciregs_t *) si_setcoreidx(sih, sii->pub.buscoreidx);
2031         }
2032
2033         /*
2034          * Enable sb->pci interrupts.  Assume
2035          * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2036          */
2037         if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2038                 /* pci config write to set this core bit in PCIIntMask */
2039                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2040                 w |= (coremask << PCI_SBIM_SHIFT);
2041                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2042         } else {
2043                 /* set sbintvec bit for our flag number */
2044                 si_setint(sih, siflag);
2045         }
2046
2047         if (PCI(sii)) {
2048                 OR_REG(sii->osh, &pciregs->sbtopci2,
2049                        (SBTOPCI_PREF | SBTOPCI_BURST));
2050                 if (sii->pub.buscorerev >= 11) {
2051                         OR_REG(sii->osh, &pciregs->sbtopci2,
2052                                SBTOPCI_RC_READMULTI);
2053                         w = R_REG(sii->osh, &pciregs->clkrun);
2054                         W_REG(sii->osh, &pciregs->clkrun,
2055                               (w | PCI_CLKRUN_DSBL));
2056                         w = R_REG(sii->osh, &pciregs->clkrun);
2057                 }
2058
2059                 /* switch back to previous core */
2060                 si_setcoreidx(sih, idx);
2061         }
2062 }
2063
2064 uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2065 {
2066         si_info_t *sii;
2067
2068         sii = SI_INFO(sih);
2069
2070         if (!(PCIE(sii)))
2071                 return 0;
2072         return pcie_clkreq(sii->pch, mask, val);
2073 }
2074
2075 uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2076 {
2077         si_info_t *sii;
2078
2079         sii = SI_INFO(sih);
2080
2081         if (!PCIE(sii))
2082                 return 0;
2083
2084         return pcie_lcreg(sii->pch, mask, val);
2085 }
2086
2087 /* indirect way to read pcie config regs */
2088 uint si_pcie_readreg(void *sih, uint addrtype, uint offset)
2089 {
2090         return pcie_readreg(((si_info_t *) sih)->osh,
2091                             (sbpcieregs_t *) PCIEREGS(((si_info_t *) sih)),
2092                             addrtype, offset);
2093 }
2094
2095 /*
2096  * Fixup SROMless PCI device's configuration.
2097  * The current core may be changed upon return.
2098  */
2099 int si_pci_fixcfg(si_t *sih)
2100 {
2101         uint origidx, pciidx;
2102         sbpciregs_t *pciregs = NULL;
2103         sbpcieregs_t *pcieregs = NULL;
2104         void *regs = NULL;
2105         uint16 val16, *reg16 = NULL;
2106
2107         si_info_t *sii = SI_INFO(sih);
2108
2109         ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2110
2111         /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2112         /* save the current index */
2113         origidx = si_coreidx(&sii->pub);
2114
2115         /* check 'pi' is correct and fix it if not */
2116         if (sii->pub.buscoretype == PCIE_CORE_ID) {
2117                 pcieregs =
2118                     (sbpcieregs_t *) si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2119                 regs = pcieregs;
2120                 ASSERT(pcieregs != NULL);
2121                 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2122         } else if (sii->pub.buscoretype == PCI_CORE_ID) {
2123                 pciregs = (sbpciregs_t *) si_setcore(&sii->pub, PCI_CORE_ID, 0);
2124                 regs = pciregs;
2125                 ASSERT(pciregs != NULL);
2126                 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2127         }
2128         pciidx = si_coreidx(&sii->pub);
2129         val16 = R_REG(sii->osh, reg16);
2130         if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) {
2131                 val16 =
2132                     (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 &
2133                                                           ~SRSH_PI_MASK);
2134                 W_REG(sii->osh, reg16, val16);
2135         }
2136
2137         /* restore the original index */
2138         si_setcoreidx(&sii->pub, origidx);
2139
2140         pcicore_hwup(sii->pch);
2141         return 0;
2142 }
2143
2144 /* change logical "focus" to the gpio core for optimized access */
2145 void *si_gpiosetcore(si_t *sih)
2146 {
2147         return (si_setcoreidx(sih, SI_CC_IDX));
2148 }
2149
2150 /* mask&set gpiocontrol bits */
2151 uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2152 {
2153         uint regoff;
2154
2155         regoff = 0;
2156
2157         /* gpios could be shared on router platforms
2158          * ignore reservation if it's high priority (e.g., test apps)
2159          */
2160         if ((priority != GPIO_HI_PRIORITY) &&
2161             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2162                 mask = priority ? (si_gpioreservation & mask) :
2163                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
2164                 val &= mask;
2165         }
2166
2167         regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2168         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2169 }
2170
2171 /* mask&set gpio output enable bits */
2172 uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2173 {
2174         uint regoff;
2175
2176         regoff = 0;
2177
2178         /* gpios could be shared on router platforms
2179          * ignore reservation if it's high priority (e.g., test apps)
2180          */
2181         if ((priority != GPIO_HI_PRIORITY) &&
2182             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2183                 mask = priority ? (si_gpioreservation & mask) :
2184                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
2185                 val &= mask;
2186         }
2187
2188         regoff = OFFSETOF(chipcregs_t, gpioouten);
2189         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2190 }
2191
2192 /* mask&set gpio output bits */
2193 uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2194 {
2195         uint regoff;
2196
2197         regoff = 0;
2198
2199         /* gpios could be shared on router platforms
2200          * ignore reservation if it's high priority (e.g., test apps)
2201          */
2202         if ((priority != GPIO_HI_PRIORITY) &&
2203             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2204                 mask = priority ? (si_gpioreservation & mask) :
2205                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
2206                 val &= mask;
2207         }
2208
2209         regoff = OFFSETOF(chipcregs_t, gpioout);
2210         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2211 }
2212
2213 /* reserve one gpio */
2214 uint32 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2215 {
2216         si_info_t *sii;
2217
2218         sii = SI_INFO(sih);
2219
2220         /* only cores on SI_BUS share GPIO's and only applcation users need to
2221          * reserve/release GPIO
2222          */
2223         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2224                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2225                 return 0xffffffff;
2226         }
2227         /* make sure only one bit is set */
2228         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2229                 ASSERT((gpio_bitmask)
2230                        && !((gpio_bitmask) & (gpio_bitmask - 1)));
2231                 return 0xffffffff;
2232         }
2233
2234         /* already reserved */
2235         if (si_gpioreservation & gpio_bitmask)
2236                 return 0xffffffff;
2237         /* set reservation */
2238         si_gpioreservation |= gpio_bitmask;
2239
2240         return si_gpioreservation;
2241 }
2242
2243 /* release one gpio */
2244 /*
2245  * releasing the gpio doesn't change the current value on the GPIO last write value
2246  * persists till some one overwrites it
2247  */
2248
2249 uint32 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2250 {
2251         si_info_t *sii;
2252
2253         sii = SI_INFO(sih);
2254
2255         /* only cores on SI_BUS share GPIO's and only applcation users need to
2256          * reserve/release GPIO
2257          */
2258         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2259                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2260                 return 0xffffffff;
2261         }
2262         /* make sure only one bit is set */
2263         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2264                 ASSERT((gpio_bitmask)
2265                        && !((gpio_bitmask) & (gpio_bitmask - 1)));
2266                 return 0xffffffff;
2267         }
2268
2269         /* already released */
2270         if (!(si_gpioreservation & gpio_bitmask))
2271                 return 0xffffffff;
2272
2273         /* clear reservation */
2274         si_gpioreservation &= ~gpio_bitmask;
2275
2276         return si_gpioreservation;
2277 }
2278
2279 /* return the current gpioin register value */
2280 uint32 si_gpioin(si_t *sih)
2281 {
2282         si_info_t *sii;
2283         uint regoff;
2284
2285         sii = SI_INFO(sih);
2286         regoff = 0;
2287
2288         regoff = OFFSETOF(chipcregs_t, gpioin);
2289         return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
2290 }
2291
2292 /* mask&set gpio interrupt polarity bits */
2293 uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2294 {
2295         si_info_t *sii;
2296         uint regoff;
2297
2298         sii = SI_INFO(sih);
2299         regoff = 0;
2300
2301         /* gpios could be shared on router platforms */
2302         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2303                 mask = priority ? (si_gpioreservation & mask) :
2304                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
2305                 val &= mask;
2306         }
2307
2308         regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2309         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2310 }
2311
2312 /* mask&set gpio interrupt mask bits */
2313 uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2314 {
2315         si_info_t *sii;
2316         uint regoff;
2317
2318         sii = SI_INFO(sih);
2319         regoff = 0;
2320
2321         /* gpios could be shared on router platforms */
2322         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2323                 mask = priority ? (si_gpioreservation & mask) :
2324                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
2325                 val &= mask;
2326         }
2327
2328         regoff = OFFSETOF(chipcregs_t, gpiointmask);
2329         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2330 }
2331
2332 /* assign the gpio to an led */
2333 uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val)
2334 {
2335         si_info_t *sii;
2336
2337         sii = SI_INFO(sih);
2338         if (sih->ccrev < 16)
2339                 return 0xffffffff;
2340
2341         /* gpio led powersave reg */
2342         return (si_corereg
2343                 (sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
2344                  val));
2345 }
2346
2347 /* mask&set gpio timer val */
2348 uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2349 {
2350         si_info_t *sii;
2351
2352         sii = SI_INFO(sih);
2353
2354         if (sih->ccrev < 16)
2355                 return 0xffffffff;
2356
2357         return (si_corereg(sih, SI_CC_IDX,
2358                            OFFSETOF(chipcregs_t, gpiotimerval), mask,
2359                            gpiotimerval));
2360 }
2361
2362 uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2363 {
2364         si_info_t *sii;
2365         uint offs;
2366
2367         sii = SI_INFO(sih);
2368         if (sih->ccrev < 20)
2369                 return 0xffffffff;
2370
2371         offs =
2372             (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
2373              OFFSETOF(chipcregs_t, gpiopullup));
2374         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2375 }
2376
2377 uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2378 {
2379         si_info_t *sii;
2380         uint offs;
2381
2382         sii = SI_INFO(sih);
2383         if (sih->ccrev < 11)
2384                 return 0xffffffff;
2385
2386         if (regtype == GPIO_REGEVT)
2387                 offs = OFFSETOF(chipcregs_t, gpioevent);
2388         else if (regtype == GPIO_REGEVT_INTMSK)
2389                 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2390         else if (regtype == GPIO_REGEVT_INTPOL)
2391                 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2392         else
2393                 return 0xffffffff;
2394
2395         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2396 }
2397
2398 void *BCMATTACHFN(si_gpio_handler_register) (si_t *sih, uint32 event,
2399                                              bool level, gpio_handler_t cb,
2400                                              void *arg) {
2401         si_info_t *sii;
2402         gpioh_item_t *gi;
2403
2404         ASSERT(event);
2405         ASSERT(cb != NULL);
2406
2407         sii = SI_INFO(sih);
2408         if (sih->ccrev < 11)
2409                 return NULL;
2410
2411         if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
2412                 return NULL;
2413
2414         bzero(gi, sizeof(gpioh_item_t));
2415         gi->event = event;
2416         gi->handler = cb;
2417         gi->arg = arg;
2418         gi->level = level;
2419
2420         gi->next = sii->gpioh_head;
2421         sii->gpioh_head = gi;
2422
2423         return (void *)(gi);
2424 }
2425
2426 void BCMATTACHFN(si_gpio_handler_unregister) (si_t *sih, void *gpioh)
2427 {
2428         si_info_t *sii;
2429         gpioh_item_t *p, *n;
2430
2431         sii = SI_INFO(sih);
2432         if (sih->ccrev < 11)
2433                 return;
2434
2435         ASSERT(sii->gpioh_head != NULL);
2436         if ((void *)sii->gpioh_head == gpioh) {
2437                 sii->gpioh_head = sii->gpioh_head->next;
2438                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2439                 return;
2440         } else {
2441                 p = sii->gpioh_head;
2442                 n = p->next;
2443                 while (n) {
2444                         if ((void *)n == gpioh) {
2445                                 p->next = n->next;
2446                                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
2447                                 return;
2448                         }
2449                         p = n;
2450                         n = n->next;
2451                 }
2452         }
2453
2454         ASSERT(0);              /* Not found in list */
2455 }
2456
2457 void si_gpio_handler_process(si_t *sih)
2458 {
2459         si_info_t *sii;
2460         gpioh_item_t *h;
2461         uint32 status;
2462         uint32 level = si_gpioin(sih);
2463         uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
2464
2465         sii = SI_INFO(sih);
2466         for (h = sii->gpioh_head; h != NULL; h = h->next) {
2467                 if (h->handler) {
2468                         status = (h->level ? level : edge);
2469
2470                         if (status & h->event)
2471                                 h->handler(status, h->arg);
2472                 }
2473         }
2474
2475         si_gpioevent(sih, GPIO_REGEVT, edge, edge);     /* clear edge-trigger status */
2476 }
2477
2478 uint32 si_gpio_int_enable(si_t *sih, bool enable)
2479 {
2480         si_info_t *sii;
2481         uint offs;
2482
2483         sii = SI_INFO(sih);
2484         if (sih->ccrev < 11)
2485                 return 0xffffffff;
2486
2487         offs = OFFSETOF(chipcregs_t, intmask);
2488         return (si_corereg
2489                 (sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
2490 }
2491
2492 /* Return the size of the specified SOCRAM bank */
2493 static uint
2494 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index,
2495                 uint8 mem_type)
2496 {
2497         uint banksize, bankinfo;
2498         uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2499
2500         ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
2501
2502         W_REG(sii->osh, &regs->bankidx, bankidx);
2503         bankinfo = R_REG(sii->osh, &regs->bankinfo);
2504         banksize =
2505             SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
2506         return banksize;
2507 }
2508
2509 void si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
2510 {
2511         si_info_t *sii;
2512         uint origidx;
2513         uint intr_val = 0;
2514         sbsocramregs_t *regs;
2515         bool wasup;
2516         uint corerev;
2517
2518         sii = SI_INFO(sih);
2519
2520         /* Block ints and save current core */
2521         INTR_OFF(sii, intr_val);
2522         origidx = si_coreidx(sih);
2523
2524         if (!set)
2525                 *enable = *protect = 0;
2526
2527         /* Switch to SOCRAM core */
2528         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2529                 goto done;
2530
2531         /* Get info for determining size */
2532         if (!(wasup = si_iscoreup(sih)))
2533                 si_core_reset(sih, 0, 0);
2534
2535         corerev = si_corerev(sih);
2536         if (corerev >= 10) {
2537                 uint32 extcinfo;
2538                 uint8 nb;
2539                 uint8 i;
2540                 uint32 bankidx, bankinfo;
2541
2542                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
2543                 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2544                       SOCRAM_DEVRAMBANK_SHIFT);
2545                 for (i = 0; i < nb; i++) {
2546                         bankidx =
2547                             i | (SOCRAM_MEMTYPE_DEVRAM <<
2548                                  SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2549                         W_REG(sii->osh, &regs->bankidx, bankidx);
2550                         bankinfo = R_REG(sii->osh, &regs->bankinfo);
2551                         if (set) {
2552                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
2553                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
2554                                 if (*enable) {
2555                                         bankinfo |=
2556                                             (1 <<
2557                                              SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
2558                                         if (*protect)
2559                                                 bankinfo |=
2560                                                     (1 <<
2561                                                      SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
2562                                 }
2563                                 W_REG(sii->osh, &regs->bankinfo, bankinfo);
2564                         } else if (i == 0) {
2565                                 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
2566                                         *enable = 1;
2567                                         if (bankinfo &
2568                                             SOCRAM_BANKINFO_DEVRAMPRO_MASK)
2569                                                 *protect = 1;
2570                                 }
2571                         }
2572                 }
2573         }
2574
2575         /* Return to previous state and core */
2576         if (!wasup)
2577                 si_core_disable(sih, 0);
2578         si_setcoreidx(sih, origidx);
2579
2580  done:
2581         INTR_RESTORE(sii, intr_val);
2582 }
2583
2584 bool si_socdevram_pkg(si_t *sih)
2585 {
2586         if (si_socdevram_size(sih) > 0)
2587                 return TRUE;
2588         else
2589                 return FALSE;
2590 }
2591
2592 uint32 si_socdevram_size(si_t *sih)
2593 {
2594         si_info_t *sii;
2595         uint origidx;
2596         uint intr_val = 0;
2597         uint32 memsize = 0;
2598         sbsocramregs_t *regs;
2599         bool wasup;
2600         uint corerev;
2601
2602         sii = SI_INFO(sih);
2603
2604         /* Block ints and save current core */
2605         INTR_OFF(sii, intr_val);
2606         origidx = si_coreidx(sih);
2607
2608         /* Switch to SOCRAM core */
2609         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2610                 goto done;
2611
2612         /* Get info for determining size */
2613         if (!(wasup = si_iscoreup(sih)))
2614                 si_core_reset(sih, 0, 0);
2615
2616         corerev = si_corerev(sih);
2617         if (corerev >= 10) {
2618                 uint32 extcinfo;
2619                 uint8 nb;
2620                 uint8 i;
2621
2622                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
2623                 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >>
2624                        SOCRAM_DEVRAMBANK_SHIFT));
2625                 for (i = 0; i < nb; i++)
2626                         memsize +=
2627                             socram_banksize(sii, regs, i,
2628                                             SOCRAM_MEMTYPE_DEVRAM);
2629         }
2630
2631         /* Return to previous state and core */
2632         if (!wasup)
2633                 si_core_disable(sih, 0);
2634         si_setcoreidx(sih, origidx);
2635
2636  done:
2637         INTR_RESTORE(sii, intr_val);
2638
2639         return memsize;
2640 }
2641
2642 /* Return the RAM size of the SOCRAM core */
2643 uint32 si_socram_size(si_t *sih)
2644 {
2645         si_info_t *sii;
2646         uint origidx;
2647         uint intr_val = 0;
2648
2649         sbsocramregs_t *regs;
2650         bool wasup;
2651         uint corerev;
2652         uint32 coreinfo;
2653         uint memsize = 0;
2654
2655         sii = SI_INFO(sih);
2656
2657         /* Block ints and save current core */
2658         INTR_OFF(sii, intr_val);
2659         origidx = si_coreidx(sih);
2660
2661         /* Switch to SOCRAM core */
2662         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2663                 goto done;
2664
2665         /* Get info for determining size */
2666         if (!(wasup = si_iscoreup(sih)))
2667                 si_core_reset(sih, 0, 0);
2668         corerev = si_corerev(sih);
2669         coreinfo = R_REG(sii->osh, &regs->coreinfo);
2670
2671         /* Calculate size from coreinfo based on rev */
2672         if (corerev == 0)
2673                 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
2674         else if (corerev < 3) {
2675                 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
2676                 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2677         } else if ((corerev <= 7) || (corerev == 12)) {
2678                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2679                 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
2680                 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
2681                 if (lss != 0)
2682                         nb--;
2683                 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
2684                 if (lss != 0)
2685                         memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
2686         } else {
2687                 uint8 i;
2688                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2689                 for (i = 0; i < nb; i++)
2690                         memsize +=
2691                             socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
2692         }
2693
2694         /* Return to previous state and core */
2695         if (!wasup)
2696                 si_core_disable(sih, 0);
2697         si_setcoreidx(sih, origidx);
2698
2699  done:
2700         INTR_RESTORE(sii, intr_val);
2701
2702         return memsize;
2703 }
2704
2705 void si_chipcontrl_epa4331(si_t *sih, bool on)
2706 {
2707         si_info_t *sii;
2708         chipcregs_t *cc;
2709         uint origidx;
2710         uint32 val;
2711
2712         sii = SI_INFO(sih);
2713         origidx = si_coreidx(sih);
2714
2715         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2716
2717         val = R_REG(sii->osh, &cc->chipcontrol);
2718
2719         if (on) {
2720                 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
2721                         /* Ext PA Controls for 4331 12x9 Package */
2722                         W_REG(sii->osh, &cc->chipcontrol, val |
2723                               (CCTRL4331_EXTPA_EN |
2724                                CCTRL4331_EXTPA_ON_GPIO2_5));
2725                 } else {
2726                         /* Ext PA Controls for 4331 12x12 Package */
2727                         W_REG(sii->osh, &cc->chipcontrol,
2728                               val | (CCTRL4331_EXTPA_EN));
2729                 }
2730         } else {
2731                 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2732                 W_REG(sii->osh, &cc->chipcontrol, val);
2733         }
2734
2735         si_setcoreidx(sih, origidx);
2736 }
2737
2738 /* Enable BT-COEX & Ex-PA for 4313 */
2739 void si_epa_4313war(si_t *sih)
2740 {
2741         si_info_t *sii;
2742         chipcregs_t *cc;
2743         uint origidx;
2744
2745         sii = SI_INFO(sih);
2746         origidx = si_coreidx(sih);
2747
2748         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
2749
2750         /* EPA Fix */
2751         W_REG(sii->osh, &cc->gpiocontrol,
2752               R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2753
2754         si_setcoreidx(sih, origidx);
2755 }
2756
2757 /* check if the device is removed */
2758 bool si_deviceremoved(si_t *sih)
2759 {
2760         uint32 w;
2761         si_info_t *sii;
2762
2763         sii = SI_INFO(sih);
2764
2765         switch (BUSTYPE(sih->bustype)) {
2766         case PCI_BUS:
2767                 ASSERT(sii->osh != NULL);
2768                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
2769                 if ((w & 0xFFFF) != VENDOR_BROADCOM)
2770                         return TRUE;
2771                 break;
2772         }
2773         return FALSE;
2774 }
2775
2776 bool si_is_sprom_available(si_t *sih)
2777 {
2778         if (sih->ccrev >= 31) {
2779                 si_info_t *sii;
2780                 uint origidx;
2781                 chipcregs_t *cc;
2782                 uint32 sromctrl;
2783
2784                 if ((sih->cccaps & CC_CAP_SROM) == 0)
2785                         return FALSE;
2786
2787                 sii = SI_INFO(sih);
2788                 origidx = sii->curidx;
2789                 cc = si_setcoreidx(sih, SI_CC_IDX);
2790                 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
2791                 si_setcoreidx(sih, origidx);
2792                 return (sromctrl & SRC_PRESENT);
2793         }
2794
2795         switch (CHIPID(sih->chip)) {
2796         case BCM4329_CHIP_ID:
2797                 return (sih->chipst & CST4329_SPROM_SEL) != 0;
2798         case BCM4319_CHIP_ID:
2799                 return (sih->chipst & CST4319_SPROM_SEL) != 0;
2800         case BCM4336_CHIP_ID:
2801                 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
2802         case BCM4330_CHIP_ID:
2803                 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
2804         case BCM4313_CHIP_ID:
2805                 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
2806         case BCM4331_CHIP_ID:
2807                 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
2808         default:
2809                 return TRUE;
2810         }
2811 }
2812
2813 bool si_is_otp_disabled(si_t *sih)
2814 {
2815         switch (CHIPID(sih->chip)) {
2816         case BCM4329_CHIP_ID:
2817                 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
2818                     CST4329_OTP_PWRDN;
2819         case BCM4319_CHIP_ID:
2820                 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
2821                     CST4319_OTP_PWRDN;
2822         case BCM4336_CHIP_ID:
2823                 return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
2824         case BCM4330_CHIP_ID:
2825                 return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
2826         case BCM4313_CHIP_ID:
2827                 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
2828                 /* These chips always have their OTP on */
2829         case BCM43224_CHIP_ID:
2830         case BCM43225_CHIP_ID:
2831         case BCM43421_CHIP_ID:
2832         case BCM43235_CHIP_ID:
2833         case BCM43236_CHIP_ID:
2834         case BCM43238_CHIP_ID:
2835         case BCM4331_CHIP_ID:
2836         default:
2837                 return FALSE;
2838         }
2839 }
2840
2841 bool si_is_otp_powered(si_t *sih)
2842 {
2843         if (PMUCTL_ENAB(sih))
2844                 return si_pmu_is_otp_powered(sih, si_osh(sih));
2845         return TRUE;
2846 }
2847
2848 void si_otp_power(si_t *sih, bool on)
2849 {
2850         if (PMUCTL_ENAB(sih))
2851                 si_pmu_otp_power(sih, si_osh(sih), on);
2852         OSL_DELAY(1000);
2853 }
2854
2855 bool
2856 #if defined(BCMDBG)
2857 si_is_sprom_enabled(si_t *sih)
2858 #else
2859 BCMATTACHFN(si_is_sprom_enabled) (si_t *sih)
2860 #endif
2861 {
2862
2863         return TRUE;
2864 }
2865
2866 void
2867 #if defined(BCMDBG)
2868 si_sprom_enable(si_t *sih, bool enable)
2869 #else
2870 BCMATTACHFN(si_sprom_enable) (si_t *sih, bool enable)
2871 #endif
2872 {
2873         if (PMUCTL_ENAB(sih))
2874                 si_pmu_sprom_enable(sih, si_osh(sih), enable);
2875 }
2876
2877 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
2878 int si_cis_source(si_t *sih)
2879 {
2880         /* Many chips have the same mapping of their chipstatus field */
2881         static const uint cis_sel[] =
2882             { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
2883         static const uint cis_43236_sel[] =
2884             { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_OTP };
2885
2886         /* PCI chips use SROM format instead of CIS */
2887         if (BUSTYPE(sih->bustype) == PCI_BUS)
2888                 return BCME_NOTFOUND;
2889
2890         switch (CHIPID(sih->chip)) {
2891         case BCM43235_CHIP_ID:
2892         case BCM43236_CHIP_ID:
2893         case BCM43238_CHIP_ID:{
2894                         uint8 strap =
2895                             (sih->
2896                              chipst & CST4322_SPROM_OTP_SEL_MASK) >>
2897                             CST4322_SPROM_OTP_SEL_SHIFT;
2898                         return ((strap >=
2899                                  sizeof(cis_sel)) ? CIS_DEFAULT :
2900                                 cis_43236_sel[strap]);
2901                 }
2902
2903         case BCM4329_CHIP_ID:
2904                 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >=
2905                         sizeof(cis_sel)) ? CIS_DEFAULT : cis_sel[(sih->
2906                                                                   chipst &
2907                                                                   CST4329_SPROM_OTP_SEL_MASK)];
2908         case BCM4319_CHIP_ID:{
2909                         uint cis_sel4319 =
2910                             ((sih->
2911                               chipst & CST4319_SPROM_OTP_SEL_MASK) >>
2912                              CST4319_SPROM_OTP_SEL_SHIFT);
2913                         return (cis_sel4319 >=
2914                                 sizeof(cis_sel)) ? CIS_DEFAULT :
2915                             cis_sel[cis_sel4319];
2916                 }
2917         case BCM4336_CHIP_ID:{
2918                         if (sih->chipst & CST4336_SPROM_PRESENT)
2919                                 return CIS_SROM;
2920                         if (sih->chipst & CST4336_OTP_PRESENT)
2921                                 return CIS_OTP;
2922                         return CIS_DEFAULT;
2923                 }
2924         case BCM4330_CHIP_ID:{
2925                         if (sih->chipst & CST4330_SPROM_PRESENT)
2926                                 return CIS_SROM;
2927                         if (sih->chipst & CST4330_OTP_PRESENT)
2928                                 return CIS_OTP;
2929                         return CIS_DEFAULT;
2930                 }
2931         default:
2932                 return CIS_DEFAULT;
2933         }
2934 }