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