Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[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 <linux/kernel.h>
18 #include <linux/string.h>
19 #include <bcmdefs.h>
20 #include <osl.h>
21 #include <linuxver.h>
22 #include <bcmutils.h>
23 #include <siutils.h>
24 #include <bcmdevs.h>
25 #include <hndsoc.h>
26 #include <sbchipc.h>
27 #include <pci_core.h>
28 #include <pcie_core.h>
29 #include <nicpci.h>
30 #include <bcmnvram.h>
31 #include <bcmsrom.h>
32 #include <pcicfg.h>
33 #include <sbsocram.h>
34 #ifdef BCMSDIO
35 #include <bcmsdh.h>
36 #include <sdio.h>
37 #include <sbsdio.h>
38 #include <sbhnddma.h>
39 #include <sbsdpcmdev.h>
40 #include <bcmsdpcm.h>
41 #endif                          /* BCMSDIO */
42 #include <hndpmu.h>
43
44 /* this file now contains only definitions for sb functions, only necessary
45 *for devices using Sonics backplanes (bcm4329)
46 */
47
48 /* if an amba SDIO device is supported, please further restrict the inclusion
49  * of this file
50  */
51 #ifdef BCMSDIO
52 #include "siutils_priv.h"
53 #endif
54
55 /* local prototypes */
56 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
57                               void *regs, uint bustype, void *sdh, char **vars,
58                               uint *varsz);
59 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
60                             void *sdh);
61 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
62                              u32 savewin, uint *origidx, void *regs);
63 static void si_nvram_process(si_info_t *sii, char *pvars);
64
65 /* dev path concatenation util */
66 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
67 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
68 static bool si_ispcie(si_info_t *sii);
69 static uint socram_banksize(si_info_t *sii, sbsocramregs_t *r,
70                                         u8 idx, u8 mtype);
71
72 /* global variable to indicate reservation/release of gpio's */
73 static u32 si_gpioreservation;
74
75 /*
76  * Allocate a si handle.
77  * devid - pci device id (used to determine chip#)
78  * osh - opaque OS handle
79  * regs - virtual address of initial core registers
80  * bustype - pci/sb/sdio/etc
81  * vars - pointer to a pointer area for "environment" variables
82  * varsz - pointer to int to return the size of the vars
83  */
84 si_t *si_attach(uint devid, osl_t *osh, void *regs, uint bustype, void *sdh,
85                 char **vars, uint *varsz)
86 {
87         si_info_t *sii;
88
89         /* alloc si_info_t */
90         sii = kmalloc(sizeof(si_info_t), GFP_ATOMIC);
91         if (sii == NULL) {
92                 SI_ERROR(("si_attach: malloc failed!\n"));
93                 return NULL;
94         }
95
96         if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
97             NULL) {
98                 kfree(sii);
99                 return NULL;
100         }
101         sii->vars = vars ? *vars : NULL;
102         sii->varsz = varsz ? *varsz : 0;
103
104         return (si_t *) sii;
105 }
106
107 /* global kernel resource */
108 static si_info_t ksii;
109
110 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
111                             void *sdh)
112 {
113
114 #ifndef BRCM_FULLMAC
115         /* kludge to enable the clock on the 4306 which lacks a slowclock */
116         if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
117                 si_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
118 #endif
119
120 #if defined(BCMSDIO)
121         if (BUSTYPE(bustype) == SDIO_BUS) {
122                 int err;
123                 u8 clkset;
124
125                 /* Try forcing SDIO core to do ALPAvail request only */
126                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
127                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
128                                  clkset, &err);
129                 if (!err) {
130                         u8 clkval;
131
132                         /* If register supported, wait for ALPAvail and then force ALP */
133                         clkval =
134                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
135                                             SBSDIO_FUNC1_CHIPCLKCSR, NULL);
136                         if ((clkval & ~SBSDIO_AVBITS) == clkset) {
137                                 SPINWAIT(((clkval =
138                                            bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
139                                                            SBSDIO_FUNC1_CHIPCLKCSR,
140                                                            NULL)),
141                                           !SBSDIO_ALPAV(clkval)),
142                                          PMU_MAX_TRANSITION_DLY);
143                                 if (!SBSDIO_ALPAV(clkval)) {
144                                         SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval));
145                                         return false;
146                                 }
147                                 clkset =
148                                     SBSDIO_FORCE_HW_CLKREQ_OFF |
149                                     SBSDIO_FORCE_ALP;
150                                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
151                                                  SBSDIO_FUNC1_CHIPCLKCSR,
152                                                  clkset, &err);
153                                 udelay(65);
154                         }
155                 }
156
157                 /* Also, disable the extra SDIO pull-ups */
158                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
159                                  NULL);
160         }
161 #endif                          /* defined(BCMSDIO) */
162
163         return true;
164 }
165
166 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
167                              u32 savewin, uint *origidx, void *regs)
168 {
169         bool pci, pcie;
170         uint i;
171         uint pciidx, pcieidx, pcirev, pcierev;
172
173         cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
174         ASSERT(cc);
175
176         /* get chipcommon rev */
177         sii->pub.ccrev = (int)si_corerev(&sii->pub);
178
179         /* get chipcommon chipstatus */
180         if (sii->pub.ccrev >= 11)
181                 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
182
183         /* get chipcommon capabilites */
184         sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
185         /* get chipcommon extended capabilities */
186
187 #ifndef BRCM_FULLMAC
188         if (sii->pub.ccrev >= 35)
189                 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
190 #endif
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 #ifdef BRCM_FULLMAC
251         SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
252                 sii->pub.buscoretype, sii->pub.buscorerev));
253
254         /* Make sure any on-chip ARM is off (in case strapping is wrong),
255         * or downloaded code was
256         * already running.
257         */
258         if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
259                 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
260                         si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
261                         si_core_disable(&sii->pub, 0);
262         }
263 #else
264         if (pci && pcie) {
265                 if (si_ispcie(sii))
266                         pci = false;
267                 else
268                         pcie = false;
269         }
270         if (pci) {
271                 sii->pub.buscoretype = PCI_CORE_ID;
272                 sii->pub.buscorerev = pcirev;
273                 sii->pub.buscoreidx = pciidx;
274         } else if (pcie) {
275                 sii->pub.buscoretype = PCIE_CORE_ID;
276                 sii->pub.buscorerev = pcierev;
277                 sii->pub.buscoreidx = pcieidx;
278         }
279
280         SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
281                  sii->pub.buscoretype, sii->pub.buscorerev));
282
283         /* fixup necessary chip/core configurations */
284         if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
285                 if (SI_FAST(sii)) {
286                         if (!sii->pch) {
287                                 sii->pch = (void *)pcicore_init(
288                                         &sii->pub, sii->osh,
289                                         (void *)PCIEREGS(sii));
290                                 if (sii->pch == NULL)
291                                         return false;
292                         }
293                 }
294                 if (si_pci_fixcfg(&sii->pub)) {
295                         SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
296                         return false;
297                 }
298         }
299 #endif
300         /* return to the original core */
301         si_setcoreidx(&sii->pub, *origidx);
302
303         return true;
304 }
305
306 static __used void si_nvram_process(si_info_t *sii, char *pvars)
307 {
308         uint w = 0;
309
310         /* get boardtype and boardrev */
311         switch (BUSTYPE(sii->pub.bustype)) {
312         case PCI_BUS:
313                 /* do a pci config read to get subsystem id and subvendor id */
314                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(u32));
315                 /* Let nvram variables override subsystem Vend/ID */
316                 sii->pub.boardvendor = (u16)si_getdevpathintvar(&sii->pub,
317                         "boardvendor");
318                 if (sii->pub.boardvendor == 0)
319                         sii->pub.boardvendor = w & 0xffff;
320                 else
321                         SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii->pub.boardvendor, w & 0xffff));
322                 sii->pub.boardtype = (u16)si_getdevpathintvar(&sii->pub,
323                         "boardtype");
324                 if (sii->pub.boardtype == 0)
325                         sii->pub.boardtype = (w >> 16) & 0xffff;
326                 else
327                         SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii->pub.boardtype, (w >> 16) & 0xffff));
328                 break;
329
330 #ifdef BCMSDIO
331         case SDIO_BUS:
332 #endif
333                 sii->pub.boardvendor = getintvar(pvars, "manfid");
334                 sii->pub.boardtype = getintvar(pvars, "prodid");
335                 break;
336
337 #ifdef BCMSDIO
338         case SPI_BUS:
339                 sii->pub.boardvendor = VENDOR_BROADCOM;
340                 sii->pub.boardtype = SPI_BOARD;
341                 break;
342 #endif
343
344         case SI_BUS:
345         case JTAG_BUS:
346                 sii->pub.boardvendor = VENDOR_BROADCOM;
347                 sii->pub.boardtype = getintvar(pvars, "prodid");
348                 if (pvars == NULL || (sii->pub.boardtype == 0)) {
349                         sii->pub.boardtype = getintvar(NULL, "boardtype");
350                         if (sii->pub.boardtype == 0)
351                                 sii->pub.boardtype = 0xffff;
352                 }
353                 break;
354         }
355
356         if (sii->pub.boardtype == 0) {
357                 SI_ERROR(("si_doattach: unknown board type\n"));
358                 ASSERT(sii->pub.boardtype);
359         }
360
361         sii->pub.boardflags = getintvar(pvars, "boardflags");
362 }
363
364 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
365 /* this has been customized for the bcm 4329 ONLY */
366 #ifdef BCMSDIO
367 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
368                               void *regs, uint bustype, void *sdh,
369                               char **vars, uint *varsz)
370 {
371         struct si_pub *sih = &sii->pub;
372         u32 w, savewin;
373         chipcregs_t *cc;
374         char *pvars = NULL;
375         uint origidx;
376
377         ASSERT(GOODREGS(regs));
378
379         bzero((unsigned char *) sii, sizeof(si_info_t));
380
381         savewin = 0;
382
383         sih->buscoreidx = BADIDX;
384
385         sii->curmap = regs;
386         sii->sdh = sdh;
387         sii->osh = osh;
388
389         /* find Chipcommon address */
390         cc = (chipcregs_t *) sii->curmap;
391         sih->bustype = bustype;
392
393         if (bustype != BUSTYPE(bustype)) {
394                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
395                 return NULL;
396         }
397
398         /* bus/core/clk setup for register access */
399         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
400                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
401                           bustype));
402                 return NULL;
403         }
404
405         /* ChipID recognition.
406          *   We assume we can read chipid at offset 0 from the regs arg.
407          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
408          *   some way of recognizing them needs to be added here.
409          */
410         w = R_REG(osh, &cc->chipid);
411         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
412         /* Might as wll fill in chip id rev & pkg */
413         sih->chip = w & CID_ID_MASK;
414         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
415         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
416
417         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) &&
418                 (sih->chippkg != BCM4329_289PIN_PKG_ID))
419                         sih->chippkg = BCM4329_182PIN_PKG_ID;
420
421         sih->issim = IS_SIM(sih->chippkg);
422
423         /* scan for cores */
424         /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
425         sb_scan(&sii->pub, regs, devid);
426
427         /* no cores found, bail out */
428         if (sii->numcores == 0) {
429                 SI_ERROR(("si_doattach: could not find any cores\n"));
430                 return NULL;
431         }
432         /* bus/core/clk setup */
433         origidx = SI_CC_IDX;
434         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
435                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
436                 goto exit;
437         }
438
439 #ifdef BRCM_FULLMAC
440         pvars = NULL;
441 #else
442         /* Init nvram from flash if it exists */
443         nvram_init((void *)&(sii->pub));
444
445         /* Init nvram from sprom/otp if they exist */
446         if (srom_var_init
447             (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
448                 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
449                 goto exit;
450         }
451         pvars = vars ? *vars : NULL;
452         si_nvram_process(sii, pvars);
453 #endif
454
455         /* === NVRAM, clock is ready === */
456
457 #ifdef BRCM_FULLMAC
458         if (sii->pub.ccrev >= 20) {
459 #endif
460         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
461         W_REG(osh, &cc->gpiopullup, 0);
462         W_REG(osh, &cc->gpiopulldown, 0);
463         sb_setcoreidx(sih, origidx);
464 #ifdef BRCM_FULLMAC
465         }
466 #endif
467
468 #ifndef BRCM_FULLMAC
469         /* PMU specific initializations */
470         if (PMUCTL_ENAB(sih)) {
471                 u32 xtalfreq;
472                 si_pmu_init(sih, sii->osh);
473                 si_pmu_chip_init(sih, sii->osh);
474                 xtalfreq = getintvar(pvars, "xtalfreq");
475                 /* If xtalfreq var not available, try to measure it */
476                 if (xtalfreq == 0)
477                         xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
478                 si_pmu_pll_init(sih, sii->osh, xtalfreq);
479                 si_pmu_res_init(sih, sii->osh);
480                 si_pmu_swreg_init(sih, sii->osh);
481         }
482
483         /* setup the GPIO based LED powersave register */
484         w = getintvar(pvars, "leddc");
485         if (w == 0)
486                 w = DEFAULT_GPIOTIMERVAL;
487         sb_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
488
489 #ifdef BCMDBG
490         /* clear any previous epidiag-induced target abort */
491         sb_taclear(sih, false);
492 #endif                          /* BCMDBG */
493 #endif
494
495         return sii;
496
497  exit:
498         return NULL;
499 }
500
501 #else                           /* BCMSDIO */
502 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh,
503                               void *regs, uint bustype, void *sdh,
504                               char **vars, uint *varsz)
505 {
506         struct si_pub *sih = &sii->pub;
507         u32 w, savewin;
508         chipcregs_t *cc;
509         char *pvars = NULL;
510         uint origidx;
511
512         ASSERT(GOODREGS(regs));
513
514         bzero((unsigned char *) sii, sizeof(si_info_t));
515
516         savewin = 0;
517
518         sih->buscoreidx = BADIDX;
519
520         sii->curmap = regs;
521         sii->sdh = sdh;
522         sii->osh = osh;
523
524         /* check to see if we are a si core mimic'ing a pci core */
525         if ((bustype == PCI_BUS) &&
526             (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(u32)) ==
527              0xffffffff)) {
528                 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " "devid:0x%x\n", __func__, devid));
529                 bustype = SI_BUS;
530         }
531
532         /* find Chipcommon address */
533         if (bustype == PCI_BUS) {
534                 savewin =
535                     OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(u32));
536                 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
537                         savewin = SI_ENUM_BASE;
538                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
539                 cc = (chipcregs_t *) regs;
540         } else {
541                 cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
542         }
543
544         sih->bustype = bustype;
545         if (bustype != BUSTYPE(bustype)) {
546                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
547                 return NULL;
548         }
549
550         /* bus/core/clk setup for register access */
551         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
552                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
553                           bustype));
554                 return NULL;
555         }
556
557         /* ChipID recognition.
558          *   We assume we can read chipid at offset 0 from the regs arg.
559          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
560          *   some way of recognizing them needs to be added here.
561          */
562         w = R_REG(osh, &cc->chipid);
563         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
564         /* Might as wll fill in chip id rev & pkg */
565         sih->chip = w & CID_ID_MASK;
566         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
567         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
568
569         sih->issim = IS_SIM(sih->chippkg);
570
571         /* scan for cores */
572         if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
573                 SI_MSG(("Found chip type AI (0x%08x)\n", w));
574                 /* pass chipc address instead of original core base */
575                 ai_scan(&sii->pub, (void *)cc, devid);
576         } else {
577                 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
578                 return NULL;
579         }
580         /* no cores found, bail out */
581         if (sii->numcores == 0) {
582                 SI_ERROR(("si_doattach: could not find any cores\n"));
583                 return NULL;
584         }
585         /* bus/core/clk setup */
586         origidx = SI_CC_IDX;
587         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
588                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
589                 goto exit;
590         }
591
592         /* assume current core is CC */
593         if ((sii->pub.ccrev == 0x25)
594             &&
595             ((CHIPID(sih->chip) == BCM43236_CHIP_ID
596               || CHIPID(sih->chip) == BCM43235_CHIP_ID
597               || CHIPID(sih->chip) == BCM43238_CHIP_ID)
598              && (CHIPREV(sii->pub.chiprev) <= 2))) {
599
600                 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
601                         uint clkdiv;
602                         clkdiv = R_REG(osh, &cc->clkdiv);
603                         /* otp_clk_div is even number, 120/14 < 9mhz */
604                         clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
605                         W_REG(osh, &cc->clkdiv, clkdiv);
606                         SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
607                 }
608                 udelay(10);
609         }
610
611         /* Init nvram from flash if it exists */
612         nvram_init((void *)&(sii->pub));
613
614         /* Init nvram from sprom/otp if they exist */
615         if (srom_var_init
616             (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
617                 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
618                 goto exit;
619         }
620         pvars = vars ? *vars : NULL;
621         si_nvram_process(sii, pvars);
622
623         /* === NVRAM, clock is ready === */
624         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
625         W_REG(osh, &cc->gpiopullup, 0);
626         W_REG(osh, &cc->gpiopulldown, 0);
627         si_setcoreidx(sih, origidx);
628
629         /* PMU specific initializations */
630         if (PMUCTL_ENAB(sih)) {
631                 u32 xtalfreq;
632                 si_pmu_init(sih, sii->osh);
633                 si_pmu_chip_init(sih, sii->osh);
634                 xtalfreq = getintvar(pvars, "xtalfreq");
635                 /* If xtalfreq var not available, try to measure it */
636                 if (xtalfreq == 0)
637                         xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
638                 si_pmu_pll_init(sih, sii->osh, xtalfreq);
639                 si_pmu_res_init(sih, sii->osh);
640                 si_pmu_swreg_init(sih, sii->osh);
641         }
642
643         /* setup the GPIO based LED powersave register */
644         w = getintvar(pvars, "leddc");
645         if (w == 0)
646                 w = DEFAULT_GPIOTIMERVAL;
647         si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
648
649         if (PCIE(sii)) {
650                 ASSERT(sii->pch != NULL);
651                 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
652         }
653
654         if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
655             (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
656                 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
657                 if (CHIPREV(sih->chiprev) == 0) {
658                         SI_MSG(("Applying 43224A0 WARs\n"));
659                         si_corereg(sih, SI_CC_IDX,
660                                    offsetof(chipcregs_t, chipcontrol),
661                                    CCTRL43224_GPIO_TOGGLE,
662                                    CCTRL43224_GPIO_TOGGLE);
663                         si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
664                                            CCTRL_43224A0_12MA_LED_DRIVE);
665                 }
666                 if (CHIPREV(sih->chiprev) >= 1) {
667                         SI_MSG(("Applying 43224B0+ WARs\n"));
668                         si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
669                                            CCTRL_43224B0_12MA_LED_DRIVE);
670                 }
671         }
672
673         if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
674                 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
675                 SI_MSG(("Applying 4313 WARs\n"));
676                 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
677                                    CCTRL_4313_12MA_LED_DRIVE);
678         }
679
680         if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
681                 /* Enable Ext PA lines depending on chip package option */
682                 si_chipcontrl_epa4331(sih, true);
683         }
684
685         return sii;
686  exit:
687         if (BUSTYPE(sih->bustype) == PCI_BUS) {
688                 if (sii->pch)
689                         pcicore_deinit(sii->pch);
690                 sii->pch = NULL;
691         }
692
693         return NULL;
694 }
695 #endif                          /* BCMSDIO */
696
697 /* may be called with core in reset */
698 void si_detach(si_t *sih)
699 {
700         si_info_t *sii;
701         uint idx;
702
703         struct si_pub *si_local = NULL;
704         bcopy(&sih, &si_local, sizeof(si_t **));
705
706         sii = SI_INFO(sih);
707
708         if (sii == NULL)
709                 return;
710
711         if (BUSTYPE(sih->bustype) == SI_BUS)
712                 for (idx = 0; idx < SI_MAXCORES; idx++)
713                         if (sii->regs[idx]) {
714                                 REG_UNMAP(sii->regs[idx]);
715                                 sii->regs[idx] = NULL;
716                         }
717
718 #ifndef BRCM_FULLMAC
719         nvram_exit((void *)si_local);   /* free up nvram buffers */
720
721         if (BUSTYPE(sih->bustype) == PCI_BUS) {
722                 if (sii->pch)
723                         pcicore_deinit(sii->pch);
724                 sii->pch = NULL;
725         }
726 #endif
727 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
728         if (sii != &ksii)
729 #endif                          /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
730                 kfree(sii);
731 }
732
733 void *si_osh(si_t *sih)
734 {
735         si_info_t *sii;
736
737         sii = SI_INFO(sih);
738         return sii->osh;
739 }
740
741 /* register driver interrupt disabling and restoring callback functions */
742 void
743 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
744                           void *intrsenabled_fn, void *intr_arg)
745 {
746         si_info_t *sii;
747
748         sii = SI_INFO(sih);
749         sii->intr_arg = intr_arg;
750         sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
751         sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
752         sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
753         /* save current core id.  when this function called, the current core
754          * must be the core which provides driver functions(il, et, wl, etc.)
755          */
756         sii->dev_coreid = sii->coreid[sii->curidx];
757 }
758
759 void si_deregister_intr_callback(si_t *sih)
760 {
761         si_info_t *sii;
762
763         sii = SI_INFO(sih);
764         sii->intrsoff_fn = NULL;
765 }
766
767 uint si_flag(si_t *sih)
768 {
769         if (CHIPTYPE(sih->socitype) == SOCI_AI)
770                 return ai_flag(sih);
771         else {
772                 ASSERT(0);
773                 return 0;
774         }
775 }
776
777 void si_setint(si_t *sih, int siflag)
778 {
779         if (CHIPTYPE(sih->socitype) == SOCI_AI)
780                 ai_setint(sih, siflag);
781         else
782                 ASSERT(0);
783 }
784
785 #ifndef BCMSDIO
786 uint si_coreid(si_t *sih)
787 {
788         si_info_t *sii;
789
790         sii = SI_INFO(sih);
791         return sii->coreid[sii->curidx];
792 }
793 #endif
794
795 uint si_coreidx(si_t *sih)
796 {
797         si_info_t *sii;
798
799         sii = SI_INFO(sih);
800         return sii->curidx;
801 }
802
803 bool si_backplane64(si_t *sih)
804 {
805         return (sih->cccaps & CC_CAP_BKPLN64) != 0;
806 }
807
808 #ifndef BCMSDIO
809 uint si_corerev(si_t *sih)
810 {
811         if (CHIPTYPE(sih->socitype) == SOCI_AI)
812                 return ai_corerev(sih);
813         else {
814                 ASSERT(0);
815                 return 0;
816         }
817 }
818 #endif
819
820 /* return index of coreid or BADIDX if not found */
821 uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
822 {
823         si_info_t *sii;
824         uint found;
825         uint i;
826
827         sii = SI_INFO(sih);
828
829         found = 0;
830
831         for (i = 0; i < sii->numcores; i++)
832                 if (sii->coreid[i] == coreid) {
833                         if (found == coreunit)
834                                 return i;
835                         found++;
836                 }
837
838         return BADIDX;
839 }
840
841 /*
842  * This function changes logical "focus" to the indicated core;
843  * must be called with interrupts off.
844  * Moreover, callers should keep interrupts off during switching out of and back to d11 core
845  */
846 void *si_setcore(si_t *sih, uint coreid, uint coreunit)
847 {
848         uint idx;
849
850         idx = si_findcoreidx(sih, coreid, coreunit);
851         if (!GOODIDX(idx))
852                 return NULL;
853
854         if (CHIPTYPE(sih->socitype) == SOCI_AI)
855                 return ai_setcoreidx(sih, idx);
856         else {
857 #ifdef BCMSDIO
858                 return sb_setcoreidx(sih, idx);
859 #else
860                 ASSERT(0);
861                 return NULL;
862 #endif
863         }
864 }
865
866 #ifndef BCMSDIO
867 void *si_setcoreidx(si_t *sih, uint coreidx)
868 {
869         if (CHIPTYPE(sih->socitype) == SOCI_AI)
870                 return ai_setcoreidx(sih, coreidx);
871         else {
872                 ASSERT(0);
873                 return NULL;
874         }
875 }
876 #endif
877
878 /* Turn off interrupt as required by sb_setcore, before switch core */
879 void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
880 {
881         void *cc;
882         si_info_t *sii;
883
884         sii = SI_INFO(sih);
885
886         if (SI_FAST(sii)) {
887                 /* Overloading the origidx variable to remember the coreid,
888                  * this works because the core ids cannot be confused with
889                  * core indices.
890                  */
891                 *origidx = coreid;
892                 if (coreid == CC_CORE_ID)
893                         return (void *)CCREGS_FAST(sii);
894                 else if (coreid == sih->buscoretype)
895                         return (void *)PCIEREGS(sii);
896         }
897         INTR_OFF(sii, *intr_val);
898         *origidx = sii->curidx;
899         cc = si_setcore(sih, coreid, 0);
900         ASSERT(cc != NULL);
901
902         return cc;
903 }
904
905 /* restore coreidx and restore interrupt */
906 void si_restore_core(si_t *sih, uint coreid, uint intr_val)
907 {
908         si_info_t *sii;
909
910         sii = SI_INFO(sih);
911         if (SI_FAST(sii)
912             && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
913                 return;
914
915         si_setcoreidx(sih, coreid);
916         INTR_RESTORE(sii, intr_val);
917 }
918
919 u32 si_core_cflags(si_t *sih, u32 mask, u32 val)
920 {
921         if (CHIPTYPE(sih->socitype) == SOCI_AI)
922                 return ai_core_cflags(sih, mask, val);
923         else {
924                 ASSERT(0);
925                 return 0;
926         }
927 }
928
929 u32 si_core_sflags(si_t *sih, u32 mask, u32 val)
930 {
931         if (CHIPTYPE(sih->socitype) == SOCI_AI)
932                 return ai_core_sflags(sih, mask, val);
933         else {
934                 ASSERT(0);
935                 return 0;
936         }
937 }
938
939 bool si_iscoreup(si_t *sih)
940 {
941         if (CHIPTYPE(sih->socitype) == SOCI_AI)
942                 return ai_iscoreup(sih);
943         else {
944 #ifdef BCMSDIO
945                 return sb_iscoreup(sih);
946 #else
947                 ASSERT(0);
948                 return false;
949 #endif
950         }
951 }
952
953 void si_write_wrapperreg(si_t *sih, u32 offset, u32 val)
954 {
955         /* only for 4319, no requirement for SOCI_SB */
956         if (CHIPTYPE(sih->socitype) == SOCI_AI) {
957                 ai_write_wrap_reg(sih, offset, val);
958         }
959 }
960
961 uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
962 {
963
964         if (CHIPTYPE(sih->socitype) == SOCI_AI)
965                 return ai_corereg(sih, coreidx, regoff, mask, val);
966         else {
967 #ifdef BCMSDIO
968                 return sb_corereg(sih, coreidx, regoff, mask, val);
969 #else
970                 ASSERT(0);
971                 return 0;
972 #endif
973         }
974 }
975
976 void si_core_disable(si_t *sih, u32 bits)
977 {
978
979         if (CHIPTYPE(sih->socitype) == SOCI_AI)
980                 ai_core_disable(sih, bits);
981 #ifdef BCMSDIO
982         else
983                 sb_core_disable(sih, bits);
984 #endif
985 }
986
987 void si_core_reset(si_t *sih, u32 bits, u32 resetbits)
988 {
989         if (CHIPTYPE(sih->socitype) == SOCI_AI)
990                 ai_core_reset(sih, bits, resetbits);
991 #ifdef BCMSDIO
992         else
993                 sb_core_reset(sih, bits, resetbits);
994 #endif
995 }
996
997 u32 si_alp_clock(si_t *sih)
998 {
999         if (PMUCTL_ENAB(sih))
1000                 return si_pmu_alp_clock(sih, si_osh(sih));
1001
1002         return ALP_CLOCK;
1003 }
1004
1005 u32 si_ilp_clock(si_t *sih)
1006 {
1007         if (PMUCTL_ENAB(sih))
1008                 return si_pmu_ilp_clock(sih, si_osh(sih));
1009
1010         return ILP_CLOCK;
1011 }
1012
1013 /* set chip watchdog reset timer to fire in 'ticks' */
1014 #ifdef BRCM_FULLMAC
1015 void
1016 si_watchdog(si_t *sih, uint ticks)
1017 {
1018         if (PMUCTL_ENAB(sih)) {
1019
1020                 if ((sih->chip == BCM4319_CHIP_ID) && (sih->chiprev == 0) &&
1021                         (ticks != 0)) {
1022                         si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t,
1023                         clk_ctl_st), ~0, 0x2);
1024                         si_setcore(sih, USB20D_CORE_ID, 0);
1025                         si_core_disable(sih, 1);
1026                         si_setcore(sih, CC_CORE_ID, 0);
1027                 }
1028
1029                 if (ticks == 1)
1030                         ticks = 2;
1031                 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmuwatchdog),
1032                         ~0, ticks);
1033         } else {
1034                 /* instant NMI */
1035                 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, watchdog),
1036                         ~0, ticks);
1037         }
1038 }
1039 #else
1040 void si_watchdog(si_t *sih, uint ticks)
1041 {
1042         uint nb, maxt;
1043
1044         if (PMUCTL_ENAB(sih)) {
1045
1046                 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1047                     (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1048                         si_corereg(sih, SI_CC_IDX,
1049                                    offsetof(chipcregs_t, clk_ctl_st), ~0, 0x2);
1050                         si_setcore(sih, USB20D_CORE_ID, 0);
1051                         si_core_disable(sih, 1);
1052                         si_setcore(sih, CC_CORE_ID, 0);
1053                 }
1054
1055                 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1056                 /* The mips compiler uses the sllv instruction,
1057                  * so we specially handle the 32-bit case.
1058                  */
1059                 if (nb == 32)
1060                         maxt = 0xffffffff;
1061                 else
1062                         maxt = ((1 << nb) - 1);
1063
1064                 if (ticks == 1)
1065                         ticks = 2;
1066                 else if (ticks > maxt)
1067                         ticks = maxt;
1068
1069                 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmuwatchdog),
1070                            ~0, ticks);
1071         } else {
1072                 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1073                 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1074                 maxt = (1 << 28) - 1;
1075                 if (ticks > maxt)
1076                         ticks = maxt;
1077
1078                 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, watchdog), ~0,
1079                            ticks);
1080         }
1081 }
1082 #endif
1083
1084 /* return the slow clock source - LPO, XTAL, or PCI */
1085 static uint si_slowclk_src(si_info_t *sii)
1086 {
1087         chipcregs_t *cc;
1088
1089         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1090
1091         if (sii->pub.ccrev < 6) {
1092                 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1093                     (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(u32))
1094                      & PCI_CFG_GPIO_SCS))
1095                         return SCC_SS_PCI;
1096                 else
1097                         return SCC_SS_XTAL;
1098         } else if (sii->pub.ccrev < 10) {
1099                 cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
1100                 return R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK;
1101         } else                  /* Insta-clock */
1102                 return SCC_SS_XTAL;
1103 }
1104
1105 /* return the ILP (slowclock) min or max frequency */
1106 static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1107 {
1108         u32 slowclk;
1109         uint div;
1110
1111         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1112
1113         /* shouldn't be here unless we've established the chip has dynamic clk control */
1114         ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1115
1116         slowclk = si_slowclk_src(sii);
1117         if (sii->pub.ccrev < 6) {
1118                 if (slowclk == SCC_SS_PCI)
1119                         return max_freq ? (PCIMAXFREQ / 64)
1120                                 : (PCIMINFREQ / 64);
1121                 else
1122                         return max_freq ? (XTALMAXFREQ / 32)
1123                                 : (XTALMINFREQ / 32);
1124         } else if (sii->pub.ccrev < 10) {
1125                 div = 4 *
1126                     (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
1127                       SCC_CD_SHIFT) + 1);
1128                 if (slowclk == SCC_SS_LPO)
1129                         return max_freq ? LPOMAXFREQ : LPOMINFREQ;
1130                 else if (slowclk == SCC_SS_XTAL)
1131                         return max_freq ? (XTALMAXFREQ / div)
1132                                 : (XTALMINFREQ / div);
1133                 else if (slowclk == SCC_SS_PCI)
1134                         return max_freq ? (PCIMAXFREQ / div)
1135                                 : (PCIMINFREQ / div);
1136                 else
1137                         ASSERT(0);
1138         } else {
1139                 /* Chipc rev 10 is InstaClock */
1140                 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1141                 div = 4 * (div + 1);
1142                 return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
1143         }
1144         return 0;
1145 }
1146
1147 static void si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1148 {
1149         chipcregs_t *cc = (chipcregs_t *) chipcregs;
1150         uint slowmaxfreq, pll_delay, slowclk;
1151         uint pll_on_delay, fref_sel_delay;
1152
1153         pll_delay = PLL_DELAY;
1154
1155         /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1156          * since the xtal will also be powered down by dynamic clk control logic.
1157          */
1158
1159         slowclk = si_slowclk_src(sii);
1160         if (slowclk != SCC_SS_XTAL)
1161                 pll_delay += XTAL_ON_DELAY;
1162
1163         /* Starting with 4318 it is ILP that is used for the delays */
1164         slowmaxfreq =
1165             si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc);
1166
1167         pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1168         fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1169
1170         W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1171         W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1172 }
1173
1174 /* initialize power control delay registers */
1175 void si_clkctl_init(si_t *sih)
1176 {
1177         si_info_t *sii;
1178         uint origidx = 0;
1179         chipcregs_t *cc;
1180         bool fast;
1181
1182         if (!CCCTL_ENAB(sih))
1183                 return;
1184
1185         sii = SI_INFO(sih);
1186         fast = SI_FAST(sii);
1187         if (!fast) {
1188                 origidx = sii->curidx;
1189                 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1190                 if (cc == NULL)
1191                         return;
1192         } else {
1193                 cc = (chipcregs_t *) CCREGS_FAST(sii);
1194                 if (cc == NULL)
1195                         return;
1196         }
1197         ASSERT(cc != NULL);
1198
1199         /* set all Instaclk chip ILP to 1 MHz */
1200         if (sih->ccrev >= 10)
1201                 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1202                         (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1203
1204         si_clkctl_setdelay(sii, (void *)cc);
1205
1206         if (!fast)
1207                 si_setcoreidx(sih, origidx);
1208 }
1209
1210 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1211 u16 si_clkctl_fast_pwrup_delay(si_t *sih)
1212 {
1213         si_info_t *sii;
1214         uint origidx = 0;
1215         chipcregs_t *cc;
1216         uint slowminfreq;
1217         u16 fpdelay;
1218         uint intr_val = 0;
1219         bool fast;
1220
1221         sii = SI_INFO(sih);
1222         if (PMUCTL_ENAB(sih)) {
1223                 INTR_OFF(sii, intr_val);
1224                 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1225                 INTR_RESTORE(sii, intr_val);
1226                 return fpdelay;
1227         }
1228
1229         if (!CCCTL_ENAB(sih))
1230                 return 0;
1231
1232         fast = SI_FAST(sii);
1233         fpdelay = 0;
1234         if (!fast) {
1235                 origidx = sii->curidx;
1236                 INTR_OFF(sii, intr_val);
1237                 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1238                 if (cc == NULL)
1239                         goto done;
1240         } else {
1241                 cc = (chipcregs_t *) CCREGS_FAST(sii);
1242                 if (cc == NULL)
1243                         goto done;
1244         }
1245         ASSERT(cc != NULL);
1246
1247         slowminfreq = si_slowclk_freq(sii, false, cc);
1248         fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1249                    (slowminfreq - 1)) / slowminfreq;
1250
1251  done:
1252         if (!fast) {
1253                 si_setcoreidx(sih, origidx);
1254                 INTR_RESTORE(sii, intr_val);
1255         }
1256         return fpdelay;
1257 }
1258
1259 /* turn primary xtal and/or pll off/on */
1260 int si_clkctl_xtal(si_t *sih, uint what, bool on)
1261 {
1262         si_info_t *sii;
1263         u32 in, out, outen;
1264
1265         sii = SI_INFO(sih);
1266
1267         switch (BUSTYPE(sih->bustype)) {
1268
1269 #ifdef BCMSDIO
1270         case SDIO_BUS:
1271                 return -1;
1272 #endif                          /* BCMSDIO */
1273
1274         case PCI_BUS:
1275                 /* pcie core doesn't have any mapping to control the xtal pu */
1276                 if (PCIE(sii))
1277                         return -1;
1278
1279                 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(u32));
1280                 out =
1281                     OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(u32));
1282                 outen =
1283                     OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1284                                         sizeof(u32));
1285
1286                 /*
1287                  * Avoid glitching the clock if GPRS is already using it.
1288                  * We can't actually read the state of the PLLPD so we infer it
1289                  * by the value of XTAL_PU which *is* readable via gpioin.
1290                  */
1291                 if (on && (in & PCI_CFG_GPIO_XTAL))
1292                         return 0;
1293
1294                 if (what & XTAL)
1295                         outen |= PCI_CFG_GPIO_XTAL;
1296                 if (what & PLL)
1297                         outen |= PCI_CFG_GPIO_PLL;
1298
1299                 if (on) {
1300                         /* turn primary xtal on */
1301                         if (what & XTAL) {
1302                                 out |= PCI_CFG_GPIO_XTAL;
1303                                 if (what & PLL)
1304                                         out |= PCI_CFG_GPIO_PLL;
1305                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1306                                                      sizeof(u32), out);
1307                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1308                                                      sizeof(u32), outen);
1309                                 udelay(XTAL_ON_DELAY);
1310                         }
1311
1312                         /* turn pll on */
1313                         if (what & PLL) {
1314                                 out &= ~PCI_CFG_GPIO_PLL;
1315                                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1316                                                      sizeof(u32), out);
1317                                 mdelay(2);
1318                         }
1319                 } else {
1320                         if (what & XTAL)
1321                                 out &= ~PCI_CFG_GPIO_XTAL;
1322                         if (what & PLL)
1323                                 out |= PCI_CFG_GPIO_PLL;
1324                         OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1325                                              sizeof(u32), out);
1326                         OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1327                                              sizeof(u32), outen);
1328                 }
1329
1330         default:
1331                 return -1;
1332         }
1333
1334         return 0;
1335 }
1336
1337 /*
1338  *  clock control policy function throught chipcommon
1339  *
1340  *    set dynamic clk control mode (forceslow, forcefast, dynamic)
1341  *    returns true if we are forcing fast clock
1342  *    this is a wrapper over the next internal function
1343  *      to allow flexible policy settings for outside caller
1344  */
1345 bool si_clkctl_cc(si_t *sih, uint mode)
1346 {
1347         si_info_t *sii;
1348
1349         sii = SI_INFO(sih);
1350
1351         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1352         if (sih->ccrev < 6)
1353                 return false;
1354
1355         if (PCI_FORCEHT(sii))
1356                 return mode == CLK_FAST;
1357
1358         return _si_clkctl_cc(sii, mode);
1359 }
1360
1361 /* clk control mechanism through chipcommon, no policy checking */
1362 static bool _si_clkctl_cc(si_info_t *sii, uint mode)
1363 {
1364         uint origidx = 0;
1365         chipcregs_t *cc;
1366         u32 scc;
1367         uint intr_val = 0;
1368         bool fast = SI_FAST(sii);
1369
1370         /* chipcommon cores prior to rev6 don't support dynamic clock control */
1371         if (sii->pub.ccrev < 6)
1372                 return false;
1373
1374         /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1375         ASSERT(sii->pub.ccrev != 10);
1376
1377         if (!fast) {
1378                 INTR_OFF(sii, intr_val);
1379                 origidx = sii->curidx;
1380
1381                 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1382                     si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1383                     (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1384                         goto done;
1385
1386                 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
1387         } else {
1388                 cc = (chipcregs_t *) CCREGS_FAST(sii);
1389                 if (cc == NULL)
1390                         goto done;
1391         }
1392         ASSERT(cc != NULL);
1393
1394         if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1395                 goto done;
1396
1397         switch (mode) {
1398         case CLK_FAST:          /* FORCEHT, fast (pll) clock */
1399                 if (sii->pub.ccrev < 10) {
1400                         /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1401                         si_clkctl_xtal(&sii->pub, XTAL, ON);
1402                         SET_REG(sii->osh, &cc->slow_clk_ctl,
1403                                 (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1404                 } else if (sii->pub.ccrev < 20) {
1405                         OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1406                 } else {
1407                         OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1408                 }
1409
1410                 /* wait for the PLL */
1411                 if (PMUCTL_ENAB(&sii->pub)) {
1412                         u32 htavail = CCS_HTAVAIL;
1413                         SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
1414                                   == 0), PMU_MAX_TRANSITION_DLY);
1415                         ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1416                 } else {
1417                         udelay(PLL_DELAY);
1418                 }
1419                 break;
1420
1421         case CLK_DYNAMIC:       /* enable dynamic clock control */
1422                 if (sii->pub.ccrev < 10) {
1423                         scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1424                         scc &= ~(SCC_FS | SCC_IP | SCC_XC);
1425                         if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
1426                                 scc |= SCC_XC;
1427                         W_REG(sii->osh, &cc->slow_clk_ctl, scc);
1428
1429                         /* for dynamic control, we have to release our xtal_pu "force on" */
1430                         if (scc & SCC_XC)
1431                                 si_clkctl_xtal(&sii->pub, XTAL, OFF);
1432                 } else if (sii->pub.ccrev < 20) {
1433                         /* Instaclock */
1434                         AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
1435                 } else {
1436                         AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
1437                 }
1438                 break;
1439
1440         default:
1441                 ASSERT(0);
1442         }
1443
1444  done:
1445         if (!fast) {
1446                 si_setcoreidx(&sii->pub, origidx);
1447                 INTR_RESTORE(sii, intr_val);
1448         }
1449         return mode == CLK_FAST;
1450 }
1451
1452 /* Build device path. Support SI, PCI, and JTAG for now. */
1453 int si_devpath(si_t *sih, char *path, int size)
1454 {
1455         int slen;
1456
1457         ASSERT(path != NULL);
1458         ASSERT(size >= SI_DEVPATH_BUFSZ);
1459
1460         if (!path || size <= 0)
1461                 return -1;
1462
1463         switch (BUSTYPE(sih->bustype)) {
1464         case SI_BUS:
1465         case JTAG_BUS:
1466                 slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
1467                 break;
1468         case PCI_BUS:
1469                 ASSERT((SI_INFO(sih))->osh != NULL);
1470                 slen = snprintf(path, (size_t) size, "pci/%u/%u/",
1471                                 OSL_PCI_BUS((SI_INFO(sih))->osh),
1472                                 OSL_PCI_SLOT((SI_INFO(sih))->osh));
1473                 break;
1474
1475 #ifdef BCMSDIO
1476         case SDIO_BUS:
1477                 SI_ERROR(("si_devpath: device 0 assumed\n"));
1478                 slen = snprintf(path, (size_t) size, "sd/%u/", si_coreidx(sih));
1479                 break;
1480 #endif
1481         default:
1482                 slen = -1;
1483                 ASSERT(0);
1484                 break;
1485         }
1486
1487         if (slen < 0 || slen >= size) {
1488                 path[0] = '\0';
1489                 return -1;
1490         }
1491
1492         return 0;
1493 }
1494
1495 /* Get a variable, but only if it has a devpath prefix */
1496 char *si_getdevpathvar(si_t *sih, const char *name)
1497 {
1498         char varname[SI_DEVPATH_BUFSZ + 32];
1499
1500         si_devpathvar(sih, varname, sizeof(varname), name);
1501
1502         return getvar(NULL, varname);
1503 }
1504
1505 /* Get a variable, but only if it has a devpath prefix */
1506 int si_getdevpathintvar(si_t *sih, const char *name)
1507 {
1508 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1509         return getintvar(NULL, name);
1510 #else
1511         char varname[SI_DEVPATH_BUFSZ + 32];
1512
1513         si_devpathvar(sih, varname, sizeof(varname), name);
1514
1515         return getintvar(NULL, varname);
1516 #endif
1517 }
1518
1519 char *si_getnvramflvar(si_t *sih, const char *name)
1520 {
1521         return getvar(NULL, name);
1522 }
1523
1524 /* Concatenate the dev path with a varname into the given 'var' buffer
1525  * and return the 'var' pointer.
1526  * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1527  * On overflow, the first char will be set to '\0'.
1528  */
1529 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name)
1530 {
1531         uint path_len;
1532
1533         if (!var || len <= 0)
1534                 return var;
1535
1536         if (si_devpath(sih, var, len) == 0) {
1537                 path_len = strlen(var);
1538
1539                 if (strlen(name) + 1 > (uint) (len - path_len))
1540                         var[0] = '\0';
1541                 else
1542                         strncpy(var + path_len, name, len - path_len - 1);
1543         }
1544
1545         return var;
1546 }
1547
1548 /* return true if PCIE capability exists in the pci config space */
1549 static __used bool si_ispcie(si_info_t *sii)
1550 {
1551         u8 cap_ptr;
1552
1553         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1554                 return false;
1555
1556         cap_ptr =
1557             pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1558                                         NULL);
1559         if (!cap_ptr)
1560                 return false;
1561
1562         return true;
1563 }
1564
1565 #ifdef BCMSDIO
1566 /* initialize the sdio core */
1567 void si_sdio_init(si_t *sih)
1568 {
1569         si_info_t *sii = SI_INFO(sih);
1570
1571         if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1572             (sih->buscoretype == SDIOD_CORE_ID)) {
1573                 uint idx;
1574                 sdpcmd_regs_t *sdpregs;
1575
1576                 /* get the current core index */
1577                 idx = sii->curidx;
1578                 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1579
1580                 /* switch to sdio core */
1581                 sdpregs = (sdpcmd_regs_t *) si_setcore(sih, PCMCIA_CORE_ID, 0);
1582                 if (!sdpregs)
1583                         sdpregs =
1584                             (sdpcmd_regs_t *) si_setcore(sih, SDIOD_CORE_ID, 0);
1585                 ASSERT(sdpregs);
1586
1587                 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));
1588
1589                 /* enable backplane error and core interrupts */
1590                 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
1591                 W_REG(sii->osh, &sdpregs->sbintmask,
1592                       (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
1593
1594                 /* switch back to previous core */
1595                 si_setcoreidx(sih, idx);
1596         }
1597
1598         /* enable interrupts */
1599         bcmsdh_intr_enable(sii->sdh);
1600
1601 }
1602 #endif                          /* BCMSDIO */
1603
1604 bool si_pci_war16165(si_t *sih)
1605 {
1606         si_info_t *sii;
1607
1608         sii = SI_INFO(sih);
1609
1610         return PCI(sii) && (sih->buscorerev <= 10);
1611 }
1612
1613 void si_pci_up(si_t *sih)
1614 {
1615         si_info_t *sii;
1616
1617         sii = SI_INFO(sih);
1618
1619         /* if not pci bus, we're done */
1620         if (BUSTYPE(sih->bustype) != PCI_BUS)
1621                 return;
1622
1623         if (PCI_FORCEHT(sii))
1624                 _si_clkctl_cc(sii, CLK_FAST);
1625
1626         if (PCIE(sii))
1627                 pcicore_up(sii->pch, SI_PCIUP);
1628
1629 }
1630
1631 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
1632 void si_pci_sleep(si_t *sih)
1633 {
1634         si_info_t *sii;
1635
1636         sii = SI_INFO(sih);
1637
1638         pcicore_sleep(sii->pch);
1639 }
1640
1641 /* Unconfigure and/or apply various WARs when going down */
1642 void si_pci_down(si_t *sih)
1643 {
1644         si_info_t *sii;
1645
1646         sii = SI_INFO(sih);
1647
1648         /* if not pci bus, we're done */
1649         if (BUSTYPE(sih->bustype) != PCI_BUS)
1650                 return;
1651
1652         /* release FORCEHT since chip is going to "down" state */
1653         if (PCI_FORCEHT(sii))
1654                 _si_clkctl_cc(sii, CLK_DYNAMIC);
1655
1656         pcicore_down(sii->pch, SI_PCIDOWN);
1657 }
1658
1659 /*
1660  * Configure the pci core for pci client (NIC) action
1661  * coremask is the bitvec of cores by index to be enabled.
1662  */
1663 void si_pci_setup(si_t *sih, uint coremask)
1664 {
1665         si_info_t *sii;
1666         struct sbpciregs *pciregs = NULL;
1667         u32 siflag = 0, w;
1668         uint idx = 0;
1669
1670         sii = SI_INFO(sih);
1671
1672         if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1673                 return;
1674
1675         ASSERT(PCI(sii) || PCIE(sii));
1676         ASSERT(sii->pub.buscoreidx != BADIDX);
1677
1678         if (PCI(sii)) {
1679                 /* get current core index */
1680                 idx = sii->curidx;
1681
1682                 /* we interrupt on this backplane flag number */
1683                 siflag = si_flag(sih);
1684
1685                 /* switch over to pci core */
1686                 pciregs = (struct sbpciregs *)si_setcoreidx(sih, sii->pub.buscoreidx);
1687         }
1688
1689         /*
1690          * Enable sb->pci interrupts.  Assume
1691          * PCI rev 2.3 support was added in pci core rev 6 and things changed..
1692          */
1693         if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
1694                 /* pci config write to set this core bit in PCIIntMask */
1695                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(u32));
1696                 w |= (coremask << PCI_SBIM_SHIFT);
1697                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(u32), w);
1698         } else {
1699                 /* set sbintvec bit for our flag number */
1700                 si_setint(sih, siflag);
1701         }
1702
1703         if (PCI(sii)) {
1704                 OR_REG(sii->osh, &pciregs->sbtopci2,
1705                        (SBTOPCI_PREF | SBTOPCI_BURST));
1706                 if (sii->pub.buscorerev >= 11) {
1707                         OR_REG(sii->osh, &pciregs->sbtopci2,
1708                                SBTOPCI_RC_READMULTI);
1709                         w = R_REG(sii->osh, &pciregs->clkrun);
1710                         W_REG(sii->osh, &pciregs->clkrun,
1711                               (w | PCI_CLKRUN_DSBL));
1712                         w = R_REG(sii->osh, &pciregs->clkrun);
1713                 }
1714
1715                 /* switch back to previous core */
1716                 si_setcoreidx(sih, idx);
1717         }
1718 }
1719
1720 /*
1721  * Fixup SROMless PCI device's configuration.
1722  * The current core may be changed upon return.
1723  */
1724 int si_pci_fixcfg(si_t *sih)
1725 {
1726         uint origidx, pciidx;
1727         struct sbpciregs *pciregs = NULL;
1728         sbpcieregs_t *pcieregs = NULL;
1729         void *regs = NULL;
1730         u16 val16, *reg16 = NULL;
1731
1732         si_info_t *sii = SI_INFO(sih);
1733
1734         ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
1735
1736         /* Fixup PI in SROM shadow area to enable the correct PCI core access */
1737         /* save the current index */
1738         origidx = si_coreidx(&sii->pub);
1739
1740         /* check 'pi' is correct and fix it if not */
1741         if (sii->pub.buscoretype == PCIE_CORE_ID) {
1742                 pcieregs =
1743                     (sbpcieregs_t *) si_setcore(&sii->pub, PCIE_CORE_ID, 0);
1744                 regs = pcieregs;
1745                 ASSERT(pcieregs != NULL);
1746                 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
1747         } else if (sii->pub.buscoretype == PCI_CORE_ID) {
1748                 pciregs = (struct sbpciregs *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
1749                 regs = pciregs;
1750                 ASSERT(pciregs != NULL);
1751                 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
1752         }
1753         pciidx = si_coreidx(&sii->pub);
1754         val16 = R_REG(sii->osh, reg16);
1755         if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16) pciidx) {
1756                 val16 =
1757                     (u16) (pciidx << SRSH_PI_SHIFT) | (val16 &
1758                                                           ~SRSH_PI_MASK);
1759                 W_REG(sii->osh, reg16, val16);
1760         }
1761
1762         /* restore the original index */
1763         si_setcoreidx(&sii->pub, origidx);
1764
1765         pcicore_hwup(sii->pch);
1766         return 0;
1767 }
1768
1769 /* mask&set gpiocontrol bits */
1770 u32 si_gpiocontrol(si_t *sih, u32 mask, u32 val, u8 priority)
1771 {
1772         uint regoff;
1773
1774         regoff = 0;
1775
1776         /* gpios could be shared on router platforms
1777          * ignore reservation if it's high priority (e.g., test apps)
1778          */
1779         if ((priority != GPIO_HI_PRIORITY) &&
1780             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1781                 mask = priority ? (si_gpioreservation & mask) :
1782                     ((si_gpioreservation | mask) & ~(si_gpioreservation));
1783                 val &= mask;
1784         }
1785
1786         regoff = offsetof(chipcregs_t, gpiocontrol);
1787         return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
1788 }
1789
1790 /* Return the size of the specified SOCRAM bank */
1791 static uint
1792 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, u8 index,
1793                 u8 mem_type)
1794 {
1795         uint banksize, bankinfo;
1796         uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1797
1798         ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1799
1800         W_REG(sii->osh, &regs->bankidx, bankidx);
1801         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1802         banksize =
1803             SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1804         return banksize;
1805 }
1806
1807 /* Return the RAM size of the SOCRAM core */
1808 u32 si_socram_size(si_t *sih)
1809 {
1810         si_info_t *sii;
1811         uint origidx;
1812         uint intr_val = 0;
1813
1814         sbsocramregs_t *regs;
1815         bool wasup;
1816         uint corerev;
1817         u32 coreinfo;
1818         uint memsize = 0;
1819
1820         sii = SI_INFO(sih);
1821
1822         /* Block ints and save current core */
1823         INTR_OFF(sii, intr_val);
1824         origidx = si_coreidx(sih);
1825
1826         /* Switch to SOCRAM core */
1827         regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
1828         if (!regs)
1829                 goto done;
1830
1831         /* Get info for determining size */
1832         wasup = si_iscoreup(sih);
1833         if (!wasup)
1834                 si_core_reset(sih, 0, 0);
1835         corerev = si_corerev(sih);
1836         coreinfo = R_REG(sii->osh, &regs->coreinfo);
1837
1838         /* Calculate size from coreinfo based on rev */
1839         if (corerev == 0)
1840                 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1841         else if (corerev < 3) {
1842                 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1843                 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1844         } else if ((corerev <= 7) || (corerev == 12)) {
1845                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1846                 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1847                 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1848                 if (lss != 0)
1849                         nb--;
1850                 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1851                 if (lss != 0)
1852                         memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1853         } else {
1854                 u8 i;
1855                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1856                 for (i = 0; i < nb; i++)
1857                         memsize +=
1858                             socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1859         }
1860
1861         /* Return to previous state and core */
1862         if (!wasup)
1863                 si_core_disable(sih, 0);
1864         si_setcoreidx(sih, origidx);
1865
1866  done:
1867         INTR_RESTORE(sii, intr_val);
1868
1869         return memsize;
1870 }
1871
1872 void si_chipcontrl_epa4331(si_t *sih, bool on)
1873 {
1874         si_info_t *sii;
1875         chipcregs_t *cc;
1876         uint origidx;
1877         u32 val;
1878
1879         sii = SI_INFO(sih);
1880         origidx = si_coreidx(sih);
1881
1882         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1883
1884         val = R_REG(sii->osh, &cc->chipcontrol);
1885
1886         if (on) {
1887                 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
1888                         /* Ext PA Controls for 4331 12x9 Package */
1889                         W_REG(sii->osh, &cc->chipcontrol, val |
1890                               (CCTRL4331_EXTPA_EN |
1891                                CCTRL4331_EXTPA_ON_GPIO2_5));
1892                 } else {
1893                         /* Ext PA Controls for 4331 12x12 Package */
1894                         W_REG(sii->osh, &cc->chipcontrol,
1895                               val | (CCTRL4331_EXTPA_EN));
1896                 }
1897         } else {
1898                 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
1899                 W_REG(sii->osh, &cc->chipcontrol, val);
1900         }
1901
1902         si_setcoreidx(sih, origidx);
1903 }
1904
1905 /* Enable BT-COEX & Ex-PA for 4313 */
1906 void si_epa_4313war(si_t *sih)
1907 {
1908         si_info_t *sii;
1909         chipcregs_t *cc;
1910         uint origidx;
1911
1912         sii = SI_INFO(sih);
1913         origidx = si_coreidx(sih);
1914
1915         cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1916
1917         /* EPA Fix */
1918         W_REG(sii->osh, &cc->gpiocontrol,
1919               R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
1920
1921         si_setcoreidx(sih, origidx);
1922 }
1923
1924 /* check if the device is removed */
1925 bool si_deviceremoved(si_t *sih)
1926 {
1927         u32 w;
1928         si_info_t *sii;
1929
1930         sii = SI_INFO(sih);
1931
1932         switch (BUSTYPE(sih->bustype)) {
1933         case PCI_BUS:
1934                 ASSERT(sii->osh != NULL);
1935                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(u32));
1936                 if ((w & 0xFFFF) != VENDOR_BROADCOM)
1937                         return true;
1938                 break;
1939         }
1940         return false;
1941 }
1942
1943 bool si_is_sprom_available(si_t *sih)
1944 {
1945         if (sih->ccrev >= 31) {
1946                 si_info_t *sii;
1947                 uint origidx;
1948                 chipcregs_t *cc;
1949                 u32 sromctrl;
1950
1951                 if ((sih->cccaps & CC_CAP_SROM) == 0)
1952                         return false;
1953
1954                 sii = SI_INFO(sih);
1955                 origidx = sii->curidx;
1956                 cc = si_setcoreidx(sih, SI_CC_IDX);
1957                 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
1958                 si_setcoreidx(sih, origidx);
1959                 return sromctrl & SRC_PRESENT;
1960         }
1961
1962         switch (CHIPID(sih->chip)) {
1963         case BCM4329_CHIP_ID:
1964                 return (sih->chipst & CST4329_SPROM_SEL) != 0;
1965         case BCM4319_CHIP_ID:
1966                 return (sih->chipst & CST4319_SPROM_SEL) != 0;
1967         case BCM4336_CHIP_ID:
1968                 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
1969         case BCM4330_CHIP_ID:
1970                 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
1971         case BCM4313_CHIP_ID:
1972                 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
1973         case BCM4331_CHIP_ID:
1974                 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
1975         default:
1976                 return true;
1977         }
1978 }
1979
1980 bool si_is_otp_disabled(si_t *sih)
1981 {
1982         switch (CHIPID(sih->chip)) {
1983         case BCM4329_CHIP_ID:
1984                 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
1985                     CST4329_OTP_PWRDN;
1986         case BCM4319_CHIP_ID:
1987                 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
1988                     CST4319_OTP_PWRDN;
1989         case BCM4336_CHIP_ID:
1990                 return (sih->chipst & CST4336_OTP_PRESENT) == 0;
1991         case BCM4330_CHIP_ID:
1992                 return (sih->chipst & CST4330_OTP_PRESENT) == 0;
1993         case BCM4313_CHIP_ID:
1994                 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
1995                 /* These chips always have their OTP on */
1996         case BCM43224_CHIP_ID:
1997         case BCM43225_CHIP_ID:
1998         case BCM43421_CHIP_ID:
1999         case BCM43235_CHIP_ID:
2000         case BCM43236_CHIP_ID:
2001         case BCM43238_CHIP_ID:
2002         case BCM4331_CHIP_ID:
2003         default:
2004                 return false;
2005         }
2006 }
2007
2008 bool si_is_otp_powered(si_t *sih)
2009 {
2010         if (PMUCTL_ENAB(sih))
2011                 return si_pmu_is_otp_powered(sih, si_osh(sih));
2012         return true;
2013 }
2014
2015 void si_otp_power(si_t *sih, bool on)
2016 {
2017         if (PMUCTL_ENAB(sih))
2018                 si_pmu_otp_power(sih, si_osh(sih), on);
2019         udelay(1000);
2020 }
2021