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