Merge tag 'lsk-v3.10-android-15.01'
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / siutils.c
1 /*
2  * Misc utility routines for accessing chip-specific features
3  * of the SiliconBackplane-based Broadcom chips.
4  *
5  * $Copyright Open Broadcom Corporation$
6  *
7  * $Id: siutils.c 414368 2013-07-24 15:00:23Z $
8  */
9
10 #include <bcm_cfg.h>
11 #include <typedefs.h>
12 #include <bcmdefs.h>
13 #include <osl.h>
14 #include <bcmutils.h>
15 #include <siutils.h>
16 #include <bcmdevs.h>
17 #include <hndsoc.h>
18 #include <sbchipc.h>
19 #include <pcicfg.h>
20 #include <sbpcmcia.h>
21 #include <sbsocram.h>
22 #include <bcmsdh.h>
23 #include <sdio.h>
24 #include <sbsdio.h>
25 #include <sbhnddma.h>
26 #include <sbsdpcmdev.h>
27 #include <bcmsdpcm.h>
28 #include <hndpmu.h>
29 #include <dhd_config.h>
30
31 #include "siutils_priv.h"
32
33 /* local prototypes */
34 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
35                               uint bustype, void *sdh, char **vars, uint *varsz);
36 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
37 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
38         uint *origidx, void *regs);
39
40
41
42 /* global variable to indicate reservation/release of gpio's */
43 static uint32 si_gpioreservation = 0;
44
45 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
46
47 int do_4360_pcie2_war = 0;
48
49 /*
50  * Allocate a si handle.
51  * devid - pci device id (used to determine chip#)
52  * osh - opaque OS handle
53  * regs - virtual address of initial core registers
54  * bustype - pci/pcmcia/sb/sdio/etc
55  * vars - pointer to a pointer area for "environment" variables
56  * varsz - pointer to int to return the size of the vars
57  */
58 si_t *
59 si_attach(uint devid, osl_t *osh, void *regs,
60                        uint bustype, void *sdh, char **vars, uint *varsz)
61 {
62         si_info_t *sii;
63
64         /* alloc si_info_t */
65         if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
66                 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
67                 return (NULL);
68         }
69
70         if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
71                 MFREE(osh, sii, sizeof(si_info_t));
72                 return (NULL);
73         }
74         sii->vars = vars ? *vars : NULL;
75         sii->varsz = varsz ? *varsz : 0;
76
77         return (si_t *)sii;
78 }
79
80 /* global kernel resource */
81 static si_info_t ksii;
82
83 static uint32   wd_msticks;             /* watchdog timer ticks normalized to ms */
84
85 /* generic kernel variant of si_attach() */
86 si_t *
87 si_kattach(osl_t *osh)
88 {
89         static bool ksii_attached = FALSE;
90
91         if (!ksii_attached) {
92                 void *regs = NULL;
93                 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
94
95                 ASSERT(osh);
96                 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
97                                 SI_BUS, NULL,
98                                 osh != SI_OSH ? &ksii.vars : NULL,
99                                 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
100                         SI_ERROR(("si_kattach: si_doattach failed\n"));
101                         REG_UNMAP(regs);
102                         return NULL;
103                 }
104                 REG_UNMAP(regs);
105
106                 /* save ticks normalized to ms for si_watchdog_ms() */
107                 if (PMUCTL_ENAB(&ksii.pub)) {
108                                 /* based on 32KHz ILP clock */
109                                 wd_msticks = 32;
110                 } else {
111                         wd_msticks = ALP_CLOCK / 1000;
112                 }
113
114                 ksii_attached = TRUE;
115                 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
116                         ksii.pub.ccrev, wd_msticks));
117         }
118
119         return &ksii.pub;
120 }
121
122
123 static bool
124 si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
125 {
126         /* need to set memseg flag for CF card first before any sb registers access */
127         if (BUSTYPE(bustype) == PCMCIA_BUS)
128                 sii->memseg = TRUE;
129
130
131         if (BUSTYPE(bustype) == SDIO_BUS) {
132                 int err;
133                 uint8 clkset;
134
135                 /* Try forcing SDIO core to do ALPAvail request only */
136                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
137                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
138                 if (!err) {
139                         uint8 clkval;
140
141                         /* If register supported, wait for ALPAvail and then force ALP */
142                         clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
143                         if ((clkval & ~SBSDIO_AVBITS) == clkset) {
144                                 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
145                                         SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
146                                         PMU_MAX_TRANSITION_DLY);
147                                 if (!SBSDIO_ALPAV(clkval)) {
148                                         SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
149                                                 clkval));
150                                         return FALSE;
151                                 }
152                                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
153                                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
154                                         clkset, &err);
155                                 OSL_DELAY(65);
156                         }
157                 }
158
159                 /* Also, disable the extra SDIO pull-ups */
160                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
161         }
162
163
164         return TRUE;
165 }
166
167 static bool
168 si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
169         uint *origidx, void *regs)
170 {
171         bool pci, pcie, pcie_gen2 = FALSE;
172         uint i;
173         uint pciidx, pcieidx, pcirev, pcierev;
174
175         cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
176         ASSERT((uintptr)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         if (sii->pub.ccrev >= 35)
190                 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
191
192         /* get pmu rev and caps */
193         if (sii->pub.cccaps & CC_CAP_PMU) {
194                 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
195                 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
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         /* figure out bus/orignal core idx */
203         sii->pub.buscoretype = NODEV_CORE_ID;
204         sii->pub.buscorerev = (uint)NOREV;
205         sii->pub.buscoreidx = BADIDX;
206
207         pci = pcie = FALSE;
208         pcirev = pcierev = (uint)NOREV;
209         pciidx = pcieidx = BADIDX;
210
211         for (i = 0; i < sii->numcores; i++) {
212                 uint cid, crev;
213
214                 si_setcoreidx(&sii->pub, i);
215                 cid = si_coreid(&sii->pub);
216                 crev = si_corerev(&sii->pub);
217
218                 /* Display cores found */
219                 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
220                         i, cid, crev, sii->coresba[i], sii->regs[i]));
221
222                 if (BUSTYPE(bustype) == PCI_BUS) {
223                         if (cid == PCI_CORE_ID) {
224                                 pciidx = i;
225                                 pcirev = crev;
226                                 pci = TRUE;
227                         } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
228                                 pcieidx = i;
229                                 pcierev = crev;
230                                 pcie = TRUE;
231                                 if (cid == PCIE2_CORE_ID)
232                                         pcie_gen2 = TRUE;
233                         }
234                 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
235                            (cid == PCMCIA_CORE_ID)) {
236                         sii->pub.buscorerev = crev;
237                         sii->pub.buscoretype = cid;
238                         sii->pub.buscoreidx = i;
239                 }
240                 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
241                           (BUSTYPE(bustype) == SPI_BUS)) &&
242                          ((cid == PCMCIA_CORE_ID) ||
243                           (cid == SDIOD_CORE_ID))) {
244                         sii->pub.buscorerev = crev;
245                         sii->pub.buscoretype = cid;
246                         sii->pub.buscoreidx = i;
247                 }
248
249                 /* find the core idx before entering this func. */
250                 if ((savewin && (savewin == sii->coresba[i])) ||
251                     (regs == sii->regs[i]))
252                         *origidx = i;
253         }
254
255         if (pci) {
256                 sii->pub.buscoretype = PCI_CORE_ID;
257                 sii->pub.buscorerev = pcirev;
258                 sii->pub.buscoreidx = pciidx;
259         } else if (pcie) {
260                 if (pcie_gen2)
261                         sii->pub.buscoretype = PCIE2_CORE_ID;
262                 else
263                         sii->pub.buscoretype = PCIE_CORE_ID;
264                 sii->pub.buscorerev = pcierev;
265                 sii->pub.buscoreidx = pcieidx;
266         }
267
268         SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
269                  sii->pub.buscorerev));
270
271         if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
272             (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
273                 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
274
275
276         /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
277          * already running.
278          */
279         if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
280                 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
281                     si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
282                         si_core_disable(&sii->pub, 0);
283         }
284
285         /* return to the original core */
286         si_setcoreidx(&sii->pub, *origidx);
287
288         return TRUE;
289 }
290
291
292
293
294 static si_info_t *
295 si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
296                        uint bustype, void *sdh, char **vars, uint *varsz)
297 {
298         struct si_pub *sih = &sii->pub;
299         uint32 w, savewin;
300         chipcregs_t *cc;
301         char *pvars = NULL;
302         uint origidx;
303 #if !defined(_CFEZ_) || defined(CFG_WL)
304 #endif 
305         ASSERT(GOODREGS(regs));
306
307         bzero((uchar*)sii, sizeof(si_info_t));
308
309         savewin = 0;
310
311         sih->buscoreidx = BADIDX;
312
313         sii->curmap = regs;
314         sii->sdh = sdh;
315         sii->osh = osh;
316
317
318
319         /* find Chipcommon address */
320         if (bustype == PCI_BUS) {
321                 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
322                 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
323                         savewin = SI_ENUM_BASE;
324                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
325                 if (!regs)
326                         return NULL;
327                 cc = (chipcregs_t *)regs;
328         } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
329                 cc = (chipcregs_t *)sii->curmap;
330         } else {
331                 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
332         }
333
334         sih->bustype = bustype;
335         if (bustype != BUSTYPE(bustype)) {
336                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
337                         bustype, BUSTYPE(bustype)));
338                 return NULL;
339         }
340
341         /* bus/core/clk setup for register access */
342         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
343                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
344                 return NULL;
345         }
346
347         /* ChipID recognition.
348          *   We assume we can read chipid at offset 0 from the regs arg.
349          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
350          *   some way of recognizing them needs to be added here.
351          */
352         if (!cc) {
353                 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
354                 return NULL;
355         }
356         w = R_REG(osh, &cc->chipid);
357         if ((w & 0xfffff) == 148277) w -= 65532;
358         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
359         /* Might as wll fill in chip id rev & pkg */
360         sih->chip = w & CID_ID_MASK;
361         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
362         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
363
364 #if defined(HW_OOB)
365         dhd_conf_set_hw_oob_intr(sdh, sih->chip);
366 #endif
367
368         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
369                 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
370                 sih->chippkg = BCM4329_182PIN_PKG_ID;
371         }
372         sih->issim = IS_SIM(sih->chippkg);
373
374         /* scan for cores */
375         if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
376                 SI_MSG(("Found chip type SB (0x%08x)\n", w));
377                 sb_scan(&sii->pub, regs, devid);
378         } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
379                 (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) {
380                 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
381                         SI_MSG(("Found chip type AI (0x%08x)\n", w));
382                 else
383                         SI_MSG(("Found chip type NAI (0x%08x)\n", w));
384                 /* pass chipc address instead of original core base */
385                 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
386         } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
387                 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
388                 /* pass chipc address instead of original core base */
389                 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
390         } else {
391                 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
392                 return NULL;
393         }
394         /* no cores found, bail out */
395         if (sii->numcores == 0) {
396                 SI_ERROR(("si_doattach: could not find any cores\n"));
397                 return NULL;
398         }
399         /* bus/core/clk setup */
400         origidx = SI_CC_IDX;
401         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
402                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
403                 goto exit;
404         }
405
406 #if !defined(_CFEZ_) || defined(CFG_WL)
407         if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
408                 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
409                 CST4322_SPROM_PRESENT))) {
410                 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
411                 return NULL;
412         }
413
414         /* assume current core is CC */
415         if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
416                                           CHIPID(sih->chip) == BCM43235_CHIP_ID ||
417                                           CHIPID(sih->chip) == BCM43234_CHIP_ID ||
418                                           CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
419                                          (CHIPREV(sii->pub.chiprev) <= 2))) {
420
421                 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
422                         uint clkdiv;
423                         clkdiv = R_REG(osh, &cc->clkdiv);
424                         /* otp_clk_div is even number, 120/14 < 9mhz */
425                         clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
426                         W_REG(osh, &cc->clkdiv, clkdiv);
427                         SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
428                 }
429                 OSL_DELAY(10);
430         }
431
432         if (bustype == PCI_BUS) {
433
434         }
435 #endif 
436
437         pvars = NULL;
438         BCM_REFERENCE(pvars);
439
440
441
442                 if (sii->pub.ccrev >= 20) {
443                         uint32 gpiopullup = 0, gpiopulldown = 0;
444                         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
445                         ASSERT(cc != NULL);
446
447                         /* 4314/43142 has pin muxing, don't clear gpio bits */
448                         if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
449                                 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
450                                 gpiopullup |= 0x402e0;
451                                 gpiopulldown |= 0x20500;
452                         }
453
454                         W_REG(osh, &cc->gpiopullup, gpiopullup);
455                         W_REG(osh, &cc->gpiopulldown, gpiopulldown);
456                         si_setcoreidx(sih, origidx);
457                 }
458
459
460         /* clear any previous epidiag-induced target abort */
461         ASSERT(!si_taclear(sih, FALSE));
462
463         return (sii);
464
465 exit:
466
467         return NULL;
468 }
469
470 /* may be called with core in reset */
471 void
472 si_detach(si_t *sih)
473 {
474         si_info_t *sii;
475         uint idx;
476
477
478         sii = SI_INFO(sih);
479
480         if (sii == NULL)
481                 return;
482
483         if (BUSTYPE(sih->bustype) == SI_BUS)
484                 for (idx = 0; idx < SI_MAXCORES; idx++)
485                         if (sii->regs[idx]) {
486                                 REG_UNMAP(sii->regs[idx]);
487                                 sii->regs[idx] = NULL;
488                         }
489
490
491
492 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
493         if (sii != &ksii)
494 #endif  /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
495                 MFREE(sii->osh, sii, sizeof(si_info_t));
496 }
497
498 void *
499 si_osh(si_t *sih)
500 {
501         si_info_t *sii;
502
503         sii = SI_INFO(sih);
504         return sii->osh;
505 }
506
507 void
508 si_setosh(si_t *sih, osl_t *osh)
509 {
510         si_info_t *sii;
511
512         sii = SI_INFO(sih);
513         if (sii->osh != NULL) {
514                 SI_ERROR(("osh is already set....\n"));
515                 ASSERT(!sii->osh);
516         }
517         sii->osh = osh;
518 }
519
520 /* register driver interrupt disabling and restoring callback functions */
521 void
522 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
523                           void *intrsenabled_fn, void *intr_arg)
524 {
525         si_info_t *sii;
526
527         sii = SI_INFO(sih);
528         sii->intr_arg = intr_arg;
529         sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
530         sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
531         sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
532         /* save current core id.  when this function called, the current core
533          * must be the core which provides driver functions(il, et, wl, etc.)
534          */
535         sii->dev_coreid = sii->coreid[sii->curidx];
536 }
537
538 void
539 si_deregister_intr_callback(si_t *sih)
540 {
541         si_info_t *sii;
542
543         sii = SI_INFO(sih);
544         sii->intrsoff_fn = NULL;
545 }
546
547 uint
548 si_intflag(si_t *sih)
549 {
550         si_info_t *sii = SI_INFO(sih);
551
552         if (CHIPTYPE(sih->socitype) == SOCI_SB)
553                 return sb_intflag(sih);
554         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
555                 return R_REG(sii->osh, ((uint32 *)(uintptr)
556                             (sii->oob_router + OOB_STATUSA)));
557         else {
558                 ASSERT(0);
559                 return 0;
560         }
561 }
562
563 uint
564 si_flag(si_t *sih)
565 {
566         if (CHIPTYPE(sih->socitype) == SOCI_SB)
567                 return sb_flag(sih);
568         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
569                 return ai_flag(sih);
570         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
571                 return ub_flag(sih);
572         else {
573                 ASSERT(0);
574                 return 0;
575         }
576 }
577
578 uint
579 si_flag_alt(si_t *sih)
580 {
581         if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
582                 return ai_flag_alt(sih);
583         else {
584                 ASSERT(0);
585                 return 0;
586         }
587 }
588
589 void
590 si_setint(si_t *sih, int siflag)
591 {
592         if (CHIPTYPE(sih->socitype) == SOCI_SB)
593                 sb_setint(sih, siflag);
594         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
595                 ai_setint(sih, siflag);
596         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
597                 ub_setint(sih, siflag);
598         else
599                 ASSERT(0);
600 }
601
602 uint
603 si_coreid(si_t *sih)
604 {
605         si_info_t *sii;
606
607         sii = SI_INFO(sih);
608         return sii->coreid[sii->curidx];
609 }
610
611 uint
612 si_coreidx(si_t *sih)
613 {
614         si_info_t *sii;
615
616         sii = SI_INFO(sih);
617         return sii->curidx;
618 }
619
620 /* return the core-type instantiation # of the current core */
621 uint
622 si_coreunit(si_t *sih)
623 {
624         si_info_t *sii;
625         uint idx;
626         uint coreid;
627         uint coreunit;
628         uint i;
629
630         sii = SI_INFO(sih);
631         coreunit = 0;
632
633         idx = sii->curidx;
634
635         ASSERT(GOODREGS(sii->curmap));
636         coreid = si_coreid(sih);
637
638         /* count the cores of our type */
639         for (i = 0; i < idx; i++)
640                 if (sii->coreid[i] == coreid)
641                         coreunit++;
642
643         return (coreunit);
644 }
645
646 uint
647 si_corevendor(si_t *sih)
648 {
649         if (CHIPTYPE(sih->socitype) == SOCI_SB)
650                 return sb_corevendor(sih);
651         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
652                 return ai_corevendor(sih);
653         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
654                 return ub_corevendor(sih);
655         else {
656                 ASSERT(0);
657                 return 0;
658         }
659 }
660
661 bool
662 si_backplane64(si_t *sih)
663 {
664         return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
665 }
666
667 uint
668 si_corerev(si_t *sih)
669 {
670         if (CHIPTYPE(sih->socitype) == SOCI_SB)
671                 return sb_corerev(sih);
672         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
673                 return ai_corerev(sih);
674         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
675                 return ub_corerev(sih);
676         else {
677                 ASSERT(0);
678                 return 0;
679         }
680 }
681
682 /* return index of coreid or BADIDX if not found */
683 uint
684 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
685 {
686         si_info_t *sii;
687         uint found;
688         uint i;
689
690         sii = SI_INFO(sih);
691
692         found = 0;
693
694         for (i = 0; i < sii->numcores; i++)
695                 if (sii->coreid[i] == coreid) {
696                         if (found == coreunit)
697                                 return (i);
698                         found++;
699                 }
700
701         return (BADIDX);
702 }
703
704 /* return list of found cores */
705 uint
706 si_corelist(si_t *sih, uint coreid[])
707 {
708         si_info_t *sii;
709
710         sii = SI_INFO(sih);
711
712         bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
713         return (sii->numcores);
714 }
715
716 /* return current wrapper mapping */
717 void *
718 si_wrapperregs(si_t *sih)
719 {
720         si_info_t *sii;
721
722         sii = SI_INFO(sih);
723         ASSERT(GOODREGS(sii->curwrap));
724
725         return (sii->curwrap);
726 }
727
728 /* return current register mapping */
729 void *
730 si_coreregs(si_t *sih)
731 {
732         si_info_t *sii;
733
734         sii = SI_INFO(sih);
735         ASSERT(GOODREGS(sii->curmap));
736
737         return (sii->curmap);
738 }
739
740 /*
741  * This function changes logical "focus" to the indicated core;
742  * must be called with interrupts off.
743  * Moreover, callers should keep interrupts off during switching out of and back to d11 core
744  */
745 void *
746 si_setcore(si_t *sih, uint coreid, uint coreunit)
747 {
748         uint idx;
749
750         idx = si_findcoreidx(sih, coreid, coreunit);
751         if (!GOODIDX(idx))
752                 return (NULL);
753
754         if (CHIPTYPE(sih->socitype) == SOCI_SB)
755                 return sb_setcoreidx(sih, idx);
756         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
757                 return ai_setcoreidx(sih, idx);
758         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
759                 return ub_setcoreidx(sih, idx);
760         else {
761                 ASSERT(0);
762                 return NULL;
763         }
764 }
765
766 void *
767 si_setcoreidx(si_t *sih, uint coreidx)
768 {
769         if (CHIPTYPE(sih->socitype) == SOCI_SB)
770                 return sb_setcoreidx(sih, coreidx);
771         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
772                 return ai_setcoreidx(sih, coreidx);
773         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
774                 return ub_setcoreidx(sih, coreidx);
775         else {
776                 ASSERT(0);
777                 return NULL;
778         }
779 }
780
781 /* Turn off interrupt as required by sb_setcore, before switch core */
782 void *
783 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
784 {
785         void *cc;
786         si_info_t *sii;
787
788         sii = SI_INFO(sih);
789
790         if (SI_FAST(sii)) {
791                 /* Overloading the origidx variable to remember the coreid,
792                  * this works because the core ids cannot be confused with
793                  * core indices.
794                  */
795                 *origidx = coreid;
796                 if (coreid == CC_CORE_ID)
797                         return (void *)CCREGS_FAST(sii);
798                 else if (coreid == sih->buscoretype)
799                         return (void *)PCIEREGS(sii);
800         }
801         INTR_OFF(sii, *intr_val);
802         *origidx = sii->curidx;
803         cc = si_setcore(sih, coreid, 0);
804         ASSERT(cc != NULL);
805
806         return cc;
807 }
808
809 /* restore coreidx and restore interrupt */
810 void
811 si_restore_core(si_t *sih, uint coreid, uint intr_val)
812 {
813         si_info_t *sii;
814
815         sii = SI_INFO(sih);
816         if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
817                 return;
818
819         si_setcoreidx(sih, coreid);
820         INTR_RESTORE(sii, intr_val);
821 }
822
823 int
824 si_numaddrspaces(si_t *sih)
825 {
826         if (CHIPTYPE(sih->socitype) == SOCI_SB)
827                 return sb_numaddrspaces(sih);
828         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
829                 return ai_numaddrspaces(sih);
830         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
831                 return ub_numaddrspaces(sih);
832         else {
833                 ASSERT(0);
834                 return 0;
835         }
836 }
837
838 uint32
839 si_addrspace(si_t *sih, uint asidx)
840 {
841         if (CHIPTYPE(sih->socitype) == SOCI_SB)
842                 return sb_addrspace(sih, asidx);
843         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
844                 return ai_addrspace(sih, asidx);
845         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
846                 return ub_addrspace(sih, asidx);
847         else {
848                 ASSERT(0);
849                 return 0;
850         }
851 }
852
853 uint32
854 si_addrspacesize(si_t *sih, uint asidx)
855 {
856         if (CHIPTYPE(sih->socitype) == SOCI_SB)
857                 return sb_addrspacesize(sih, asidx);
858         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
859                 return ai_addrspacesize(sih, asidx);
860         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
861                 return ub_addrspacesize(sih, asidx);
862         else {
863                 ASSERT(0);
864                 return 0;
865         }
866 }
867
868 void
869 si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
870 {
871         /* Only supported for SOCI_AI */
872         if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
873                 ai_coreaddrspaceX(sih, asidx, addr, size);
874         else
875                 *size = 0;
876 }
877
878 uint32
879 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
880 {
881         if (CHIPTYPE(sih->socitype) == SOCI_SB)
882                 return sb_core_cflags(sih, mask, val);
883         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
884                 return ai_core_cflags(sih, mask, val);
885         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
886                 return ub_core_cflags(sih, mask, val);
887         else {
888                 ASSERT(0);
889                 return 0;
890         }
891 }
892
893 void
894 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
895 {
896         if (CHIPTYPE(sih->socitype) == SOCI_SB)
897                 sb_core_cflags_wo(sih, mask, val);
898         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
899                 ai_core_cflags_wo(sih, mask, val);
900         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
901                 ub_core_cflags_wo(sih, mask, val);
902         else
903                 ASSERT(0);
904 }
905
906 uint32
907 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
908 {
909         if (CHIPTYPE(sih->socitype) == SOCI_SB)
910                 return sb_core_sflags(sih, mask, val);
911         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
912                 return ai_core_sflags(sih, mask, val);
913         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
914                 return ub_core_sflags(sih, mask, val);
915         else {
916                 ASSERT(0);
917                 return 0;
918         }
919 }
920
921 bool
922 si_iscoreup(si_t *sih)
923 {
924         if (CHIPTYPE(sih->socitype) == SOCI_SB)
925                 return sb_iscoreup(sih);
926         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
927                 return ai_iscoreup(sih);
928         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
929                 return ub_iscoreup(sih);
930         else {
931                 ASSERT(0);
932                 return FALSE;
933         }
934 }
935
936 uint
937 si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
938 {
939         /* only for AI back plane chips */
940         if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
941                 return (ai_wrap_reg(sih, offset, mask, val));
942         return 0;
943 }
944
945 uint
946 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
947 {
948         if (CHIPTYPE(sih->socitype) == SOCI_SB)
949                 return sb_corereg(sih, coreidx, regoff, mask, val);
950         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
951                 return ai_corereg(sih, coreidx, regoff, mask, val);
952         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
953                 return ub_corereg(sih, coreidx, regoff, mask, val);
954         else {
955                 ASSERT(0);
956                 return 0;
957         }
958 }
959
960 void
961 si_core_disable(si_t *sih, uint32 bits)
962 {
963         if (CHIPTYPE(sih->socitype) == SOCI_SB)
964                 sb_core_disable(sih, bits);
965         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
966                 ai_core_disable(sih, bits);
967         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
968                 ub_core_disable(sih, bits);
969 }
970
971 void
972 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
973 {
974         if (CHIPTYPE(sih->socitype) == SOCI_SB)
975                 sb_core_reset(sih, bits, resetbits);
976         else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
977                 ai_core_reset(sih, bits, resetbits);
978         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
979                 ub_core_reset(sih, bits, resetbits);
980 }
981
982 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
983 int
984 si_corebist(si_t *sih)
985 {
986         uint32 cflags;
987         int result = 0;
988
989         /* Read core control flags */
990         cflags = si_core_cflags(sih, 0, 0);
991
992         /* Set bist & fgc */
993         si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
994
995         /* Wait for bist done */
996         SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
997
998         if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
999                 result = BCME_ERROR;
1000
1001         /* Reset core control flags */
1002         si_core_cflags(sih, 0xffff, cflags);
1003
1004         return result;
1005 }
1006
1007 static uint32
1008 factor6(uint32 x)
1009 {
1010         switch (x) {
1011         case CC_F6_2:   return 2;
1012         case CC_F6_3:   return 3;
1013         case CC_F6_4:   return 4;
1014         case CC_F6_5:   return 5;
1015         case CC_F6_6:   return 6;
1016         case CC_F6_7:   return 7;
1017         default:        return 0;
1018         }
1019 }
1020
1021 /* calculate the speed the SI would run at given a set of clockcontrol values */
1022 uint32
1023 si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
1024 {
1025         uint32 n1, n2, clock, m1, m2, m3, mc;
1026
1027         n1 = n & CN_N1_MASK;
1028         n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1029
1030         if (pll_type == PLL_TYPE6) {
1031                 if (m & CC_T6_MMASK)
1032                         return CC_T6_M1;
1033                 else
1034                         return CC_T6_M0;
1035         } else if ((pll_type == PLL_TYPE1) ||
1036                    (pll_type == PLL_TYPE3) ||
1037                    (pll_type == PLL_TYPE4) ||
1038                    (pll_type == PLL_TYPE7)) {
1039                 n1 = factor6(n1);
1040                 n2 += CC_F5_BIAS;
1041         } else if (pll_type == PLL_TYPE2) {
1042                 n1 += CC_T2_BIAS;
1043                 n2 += CC_T2_BIAS;
1044                 ASSERT((n1 >= 2) && (n1 <= 7));
1045                 ASSERT((n2 >= 5) && (n2 <= 23));
1046         } else if (pll_type == PLL_TYPE5) {
1047                 return (100000000);
1048         } else
1049                 ASSERT(0);
1050         /* PLL types 3 and 7 use BASE2 (25Mhz) */
1051         if ((pll_type == PLL_TYPE3) ||
1052             (pll_type == PLL_TYPE7)) {
1053                 clock = CC_CLOCK_BASE2 * n1 * n2;
1054         } else
1055                 clock = CC_CLOCK_BASE1 * n1 * n2;
1056
1057         if (clock == 0)
1058                 return 0;
1059
1060         m1 = m & CC_M1_MASK;
1061         m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1062         m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1063         mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1064
1065         if ((pll_type == PLL_TYPE1) ||
1066             (pll_type == PLL_TYPE3) ||
1067             (pll_type == PLL_TYPE4) ||
1068             (pll_type == PLL_TYPE7)) {
1069                 m1 = factor6(m1);
1070                 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1071                         m2 += CC_F5_BIAS;
1072                 else
1073                         m2 = factor6(m2);
1074                 m3 = factor6(m3);
1075
1076                 switch (mc) {
1077                 case CC_MC_BYPASS:      return (clock);
1078                 case CC_MC_M1:          return (clock / m1);
1079                 case CC_MC_M1M2:        return (clock / (m1 * m2));
1080                 case CC_MC_M1M2M3:      return (clock / (m1 * m2 * m3));
1081                 case CC_MC_M1M3:        return (clock / (m1 * m3));
1082                 default:                return (0);
1083                 }
1084         } else {
1085                 ASSERT(pll_type == PLL_TYPE2);
1086
1087                 m1 += CC_T2_BIAS;
1088                 m2 += CC_T2M2_BIAS;
1089                 m3 += CC_T2_BIAS;
1090                 ASSERT((m1 >= 2) && (m1 <= 7));
1091                 ASSERT((m2 >= 3) && (m2 <= 10));
1092                 ASSERT((m3 >= 2) && (m3 <= 7));
1093
1094                 if ((mc & CC_T2MC_M1BYP) == 0)
1095                         clock /= m1;
1096                 if ((mc & CC_T2MC_M2BYP) == 0)
1097                         clock /= m2;
1098                 if ((mc & CC_T2MC_M3BYP) == 0)
1099                         clock /= m3;
1100
1101                 return (clock);
1102         }
1103 }
1104
1105
1106
1107 /* set chip watchdog reset timer to fire in 'ticks' */
1108 void
1109 si_watchdog(si_t *sih, uint ticks)
1110 {
1111         uint nb, maxt;
1112
1113         if (PMUCTL_ENAB(sih)) {
1114
1115 #if !defined(_CFEZ_) || defined(CFG_WL)
1116                 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1117                     (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1118                         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1119                         si_setcore(sih, USB20D_CORE_ID, 0);
1120                         si_core_disable(sih, 1);
1121                         si_setcore(sih, CC_CORE_ID, 0);
1122                 }
1123 #endif 
1124
1125                         nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1126                 /* The mips compiler uses the sllv instruction,
1127                  * so we specially handle the 32-bit case.
1128                  */
1129                 if (nb == 32)
1130                         maxt = 0xffffffff;
1131                 else
1132                         maxt = ((1 << nb) - 1);
1133
1134                 if (ticks == 1)
1135                         ticks = 2;
1136                 else if (ticks > maxt)
1137                         ticks = maxt;
1138
1139                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1140         } else {
1141                 maxt = (1 << 28) - 1;
1142                 if (ticks > maxt)
1143                         ticks = maxt;
1144
1145                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1146         }
1147 }
1148
1149 /* trigger watchdog reset after ms milliseconds */
1150 void
1151 si_watchdog_ms(si_t *sih, uint32 ms)
1152 {
1153         si_watchdog(sih, wd_msticks * ms);
1154 }
1155
1156 uint32 si_watchdog_msticks(void)
1157 {
1158         return wd_msticks;
1159 }
1160
1161 bool
1162 si_taclear(si_t *sih, bool details)
1163 {
1164         return FALSE;
1165 }
1166
1167
1168
1169 /* return the slow clock source - LPO, XTAL, or PCI */
1170 static uint
1171 si_slowclk_src(si_info_t *sii)
1172 {
1173         chipcregs_t *cc;
1174
1175         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1176
1177         if (sii->pub.ccrev < 6) {
1178                 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1179                     (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1180                      PCI_CFG_GPIO_SCS))
1181                         return (SCC_SS_PCI);
1182                 else
1183                         return (SCC_SS_XTAL);
1184         } else if (sii->pub.ccrev < 10) {
1185                 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1186                 ASSERT(cc);
1187                 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1188         } else  /* Insta-clock */
1189                 return (SCC_SS_XTAL);
1190 }
1191
1192 /* return the ILP (slowclock) min or max frequency */
1193 static uint
1194 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1195 {
1196         uint32 slowclk;
1197         uint div;
1198
1199         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1200
1201         /* shouldn't be here unless we've established the chip has dynamic clk control */
1202         ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1203
1204         slowclk = si_slowclk_src(sii);
1205         if (sii->pub.ccrev < 6) {
1206                 if (slowclk == SCC_SS_PCI)
1207                         return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1208                 else
1209                         return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1210         } else if (sii->pub.ccrev < 10) {
1211                 div = 4 *
1212                         (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1213                 if (slowclk == SCC_SS_LPO)
1214                         return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1215                 else if (slowclk == SCC_SS_XTAL)
1216                         return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1217                 else if (slowclk == SCC_SS_PCI)
1218                         return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1219                 else
1220                         ASSERT(0);
1221         } else {
1222                 /* Chipc rev 10 is InstaClock */
1223                 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1224                 div = 4 * (div + 1);
1225                 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1226         }
1227         return (0);
1228 }
1229
1230 static void
1231 si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1232 {
1233         chipcregs_t *cc = (chipcregs_t *)chipcregs;
1234         uint slowmaxfreq, pll_delay, slowclk;
1235         uint pll_on_delay, fref_sel_delay;
1236
1237         pll_delay = PLL_DELAY;
1238
1239         /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1240          * since the xtal will also be powered down by dynamic clk control logic.
1241          */
1242
1243         slowclk = si_slowclk_src(sii);
1244         if (slowclk != SCC_SS_XTAL)
1245                 pll_delay += XTAL_ON_DELAY;
1246
1247         /* Starting with 4318 it is ILP that is used for the delays */
1248         slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1249
1250         pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1251         fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1252
1253         W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1254         W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1255 }
1256
1257 /* initialize power control delay registers */
1258 void
1259 si_clkctl_init(si_t *sih)
1260 {
1261         si_info_t *sii;
1262         uint origidx = 0;
1263         chipcregs_t *cc;
1264         bool fast;
1265
1266         if (!CCCTL_ENAB(sih))
1267                 return;
1268
1269         sii = SI_INFO(sih);
1270         fast = SI_FAST(sii);
1271         if (!fast) {
1272                 origidx = sii->curidx;
1273                 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1274                         return;
1275         } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1276                 return;
1277         ASSERT(cc != NULL);
1278
1279         /* set all Instaclk chip ILP to 1 MHz */
1280         if (sih->ccrev >= 10)
1281                 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1282                         (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1283
1284         si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1285
1286         OSL_DELAY(20000);
1287
1288         if (!fast)
1289                 si_setcoreidx(sih, origidx);
1290 }
1291
1292
1293 /* change logical "focus" to the gpio core for optimized access */
1294 void *
1295 si_gpiosetcore(si_t *sih)
1296 {
1297         return (si_setcoreidx(sih, SI_CC_IDX));
1298 }
1299
1300 /*
1301  * mask & set gpiocontrol bits.
1302  * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
1303  * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
1304  *   to some chip-specific purpose.
1305  */
1306 uint32
1307 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1308 {
1309         uint regoff;
1310
1311         regoff = 0;
1312
1313         /* gpios could be shared on router platforms
1314          * ignore reservation if it's high priority (e.g., test apps)
1315          */
1316         if ((priority != GPIO_HI_PRIORITY) &&
1317             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1318                 mask = priority ? (si_gpioreservation & mask) :
1319                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1320                 val &= mask;
1321         }
1322
1323         regoff = OFFSETOF(chipcregs_t, gpiocontrol);
1324         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1325 }
1326
1327 /* mask&set gpio output enable bits */
1328 uint32
1329 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1330 {
1331         uint regoff;
1332
1333         regoff = 0;
1334
1335         /* gpios could be shared on router platforms
1336          * ignore reservation if it's high priority (e.g., test apps)
1337          */
1338         if ((priority != GPIO_HI_PRIORITY) &&
1339             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1340                 mask = priority ? (si_gpioreservation & mask) :
1341                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1342                 val &= mask;
1343         }
1344
1345         regoff = OFFSETOF(chipcregs_t, gpioouten);
1346         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1347 }
1348
1349 /* mask&set gpio output bits */
1350 uint32
1351 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1352 {
1353         uint regoff;
1354
1355         regoff = 0;
1356
1357         /* gpios could be shared on router platforms
1358          * ignore reservation if it's high priority (e.g., test apps)
1359          */
1360         if ((priority != GPIO_HI_PRIORITY) &&
1361             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1362                 mask = priority ? (si_gpioreservation & mask) :
1363                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1364                 val &= mask;
1365         }
1366
1367         regoff = OFFSETOF(chipcregs_t, gpioout);
1368         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1369 }
1370
1371 /* reserve one gpio */
1372 uint32
1373 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1374 {
1375         /* only cores on SI_BUS share GPIO's and only applcation users need to
1376          * reserve/release GPIO
1377          */
1378         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1379                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1380                 return 0xffffffff;
1381         }
1382         /* make sure only one bit is set */
1383         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1384                 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1385                 return 0xffffffff;
1386         }
1387
1388         /* already reserved */
1389         if (si_gpioreservation & gpio_bitmask)
1390                 return 0xffffffff;
1391         /* set reservation */
1392         si_gpioreservation |= gpio_bitmask;
1393
1394         return si_gpioreservation;
1395 }
1396
1397 /* release one gpio */
1398 /*
1399  * releasing the gpio doesn't change the current value on the GPIO last write value
1400  * persists till some one overwrites it
1401  */
1402
1403 uint32
1404 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1405 {
1406         /* only cores on SI_BUS share GPIO's and only applcation users need to
1407          * reserve/release GPIO
1408          */
1409         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1410                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1411                 return 0xffffffff;
1412         }
1413         /* make sure only one bit is set */
1414         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1415                 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1416                 return 0xffffffff;
1417         }
1418
1419         /* already released */
1420         if (!(si_gpioreservation & gpio_bitmask))
1421                 return 0xffffffff;
1422
1423         /* clear reservation */
1424         si_gpioreservation &= ~gpio_bitmask;
1425
1426         return si_gpioreservation;
1427 }
1428
1429 /* return the current gpioin register value */
1430 uint32
1431 si_gpioin(si_t *sih)
1432 {
1433         uint regoff;
1434
1435         regoff = OFFSETOF(chipcregs_t, gpioin);
1436         return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
1437 }
1438
1439 /* mask&set gpio interrupt polarity bits */
1440 uint32
1441 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1442 {
1443         uint regoff;
1444
1445         /* gpios could be shared on router platforms */
1446         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1447                 mask = priority ? (si_gpioreservation & mask) :
1448                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1449                 val &= mask;
1450         }
1451
1452         regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
1453         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1454 }
1455
1456 /* mask&set gpio interrupt mask bits */
1457 uint32
1458 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1459 {
1460         uint regoff;
1461
1462         /* gpios could be shared on router platforms */
1463         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1464                 mask = priority ? (si_gpioreservation & mask) :
1465                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1466                 val &= mask;
1467         }
1468
1469         regoff = OFFSETOF(chipcregs_t, gpiointmask);
1470         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1471 }
1472
1473 /* assign the gpio to an led */
1474 uint32
1475 si_gpioled(si_t *sih, uint32 mask, uint32 val)
1476 {
1477         if (sih->ccrev < 16)
1478                 return 0xffffffff;
1479
1480         /* gpio led powersave reg */
1481         return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
1482 }
1483
1484 /* mask&set gpio timer val */
1485 uint32
1486 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
1487 {
1488         if (sih->ccrev < 16)
1489                 return 0xffffffff;
1490
1491         return (si_corereg(sih, SI_CC_IDX,
1492                 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
1493 }
1494
1495 uint32
1496 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
1497 {
1498         uint offs;
1499
1500         if (sih->ccrev < 20)
1501                 return 0xffffffff;
1502
1503         offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
1504         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1505 }
1506
1507 uint32
1508 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
1509 {
1510         uint offs;
1511
1512         if (sih->ccrev < 11)
1513                 return 0xffffffff;
1514
1515         if (regtype == GPIO_REGEVT)
1516                 offs = OFFSETOF(chipcregs_t, gpioevent);
1517         else if (regtype == GPIO_REGEVT_INTMSK)
1518                 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
1519         else if (regtype == GPIO_REGEVT_INTPOL)
1520                 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
1521         else
1522                 return 0xffffffff;
1523
1524         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1525 }
1526
1527 void *
1528 si_gpio_handler_register(si_t *sih, uint32 event,
1529         bool level, gpio_handler_t cb, void *arg)
1530 {
1531         si_info_t *sii;
1532         gpioh_item_t *gi;
1533
1534         ASSERT(event);
1535         ASSERT(cb != NULL);
1536
1537         sii = SI_INFO(sih);
1538         if (sih->ccrev < 11)
1539                 return NULL;
1540
1541         if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
1542                 return NULL;
1543
1544         bzero(gi, sizeof(gpioh_item_t));
1545         gi->event = event;
1546         gi->handler = cb;
1547         gi->arg = arg;
1548         gi->level = level;
1549
1550         gi->next = sii->gpioh_head;
1551         sii->gpioh_head = gi;
1552
1553         return (void *)(gi);
1554 }
1555
1556 void
1557 si_gpio_handler_unregister(si_t *sih, void *gpioh)
1558 {
1559         si_info_t *sii;
1560         gpioh_item_t *p, *n;
1561
1562         sii = SI_INFO(sih);
1563         if (sih->ccrev < 11)
1564                 return;
1565
1566         ASSERT(sii->gpioh_head != NULL);
1567         if ((void*)sii->gpioh_head == gpioh) {
1568                 sii->gpioh_head = sii->gpioh_head->next;
1569                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1570                 return;
1571         } else {
1572                 p = sii->gpioh_head;
1573                 n = p->next;
1574                 while (n) {
1575                         if ((void*)n == gpioh) {
1576                                 p->next = n->next;
1577                                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1578                                 return;
1579                         }
1580                         p = n;
1581                         n = n->next;
1582                 }
1583         }
1584
1585         ASSERT(0); /* Not found in list */
1586 }
1587
1588 void
1589 si_gpio_handler_process(si_t *sih)
1590 {
1591         si_info_t *sii;
1592         gpioh_item_t *h;
1593         uint32 level = si_gpioin(sih);
1594         uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
1595         uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
1596         uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
1597
1598         sii = SI_INFO(sih);
1599         for (h = sii->gpioh_head; h != NULL; h = h->next) {
1600                 if (h->handler) {
1601                         uint32 status = (h->level ? level : edge) & h->event;
1602                         uint32 polarity = (h->level ? levelp : edgep) & h->event;
1603
1604                         /* polarity bitval is opposite of status bitval */
1605                         if (status ^ polarity)
1606                                 h->handler(status, h->arg);
1607                 }
1608         }
1609
1610         si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
1611 }
1612
1613 uint32
1614 si_gpio_int_enable(si_t *sih, bool enable)
1615 {
1616         uint offs;
1617
1618         if (sih->ccrev < 11)
1619                 return 0xffffffff;
1620
1621         offs = OFFSETOF(chipcregs_t, intmask);
1622         return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
1623 }
1624
1625
1626 /* Return the size of the specified SOCRAM bank */
1627 static uint
1628 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
1629 {
1630         uint banksize, bankinfo;
1631         uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1632
1633         ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1634
1635         W_REG(sii->osh, &regs->bankidx, bankidx);
1636         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1637         banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1638         return banksize;
1639 }
1640
1641 void
1642 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
1643 {
1644         si_info_t *sii;
1645         uint origidx;
1646         uint intr_val = 0;
1647         sbsocramregs_t *regs;
1648         bool wasup;
1649         uint corerev;
1650
1651         sii = SI_INFO(sih);
1652
1653         /* Block ints and save current core */
1654         INTR_OFF(sii, intr_val);
1655         origidx = si_coreidx(sih);
1656
1657         if (!set)
1658                 *enable = *protect = *remap = 0;
1659
1660         /* Switch to SOCRAM core */
1661         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1662                 goto done;
1663
1664         /* Get info for determining size */
1665         if (!(wasup = si_iscoreup(sih)))
1666                 si_core_reset(sih, 0, 0);
1667
1668         corerev = si_corerev(sih);
1669         if (corerev >= 10) {
1670                 uint32 extcinfo;
1671                 uint8 nb;
1672                 uint8 i;
1673                 uint32 bankidx, bankinfo;
1674
1675                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1676                 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1677                 for (i = 0; i < nb; i++) {
1678                         bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1679                         W_REG(sii->osh, &regs->bankidx, bankidx);
1680                         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1681                         if (set) {
1682                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
1683                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
1684                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
1685                                 if (*enable) {
1686                                         bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
1687                                         if (*protect)
1688                                                 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
1689                                         if ((corerev >= 16) && *remap)
1690                                                 bankinfo |=
1691                                                         (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
1692                                 }
1693                                 W_REG(sii->osh, &regs->bankinfo, bankinfo);
1694                         }
1695                         else if (i == 0) {
1696                                 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
1697                                         *enable = 1;
1698                                         if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
1699                                                 *protect = 1;
1700                                         if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
1701                                                 *remap = 1;
1702                                 }
1703                         }
1704                 }
1705         }
1706
1707         /* Return to previous state and core */
1708         if (!wasup)
1709                 si_core_disable(sih, 0);
1710         si_setcoreidx(sih, origidx);
1711
1712 done:
1713         INTR_RESTORE(sii, intr_val);
1714 }
1715
1716 bool
1717 si_socdevram_remap_isenb(si_t *sih)
1718 {
1719         si_info_t *sii;
1720         uint origidx;
1721         uint intr_val = 0;
1722         sbsocramregs_t *regs;
1723         bool wasup, remap = FALSE;
1724         uint corerev;
1725         uint32 extcinfo;
1726         uint8 nb;
1727         uint8 i;
1728         uint32 bankidx, bankinfo;
1729
1730         sii = SI_INFO(sih);
1731
1732         /* Block ints and save current core */
1733         INTR_OFF(sii, intr_val);
1734         origidx = si_coreidx(sih);
1735
1736         /* Switch to SOCRAM core */
1737         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1738                 goto done;
1739
1740         /* Get info for determining size */
1741         if (!(wasup = si_iscoreup(sih)))
1742                 si_core_reset(sih, 0, 0);
1743
1744         corerev = si_corerev(sih);
1745         if (corerev >= 16) {
1746                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1747                 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1748                 for (i = 0; i < nb; i++) {
1749                         bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1750                         W_REG(sii->osh, &regs->bankidx, bankidx);
1751                         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1752                         if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
1753                                 remap = TRUE;
1754                                 break;
1755                         }
1756                 }
1757         }
1758
1759         /* Return to previous state and core */
1760         if (!wasup)
1761                 si_core_disable(sih, 0);
1762         si_setcoreidx(sih, origidx);
1763
1764 done:
1765         INTR_RESTORE(sii, intr_val);
1766         return remap;
1767 }
1768
1769 bool
1770 si_socdevram_pkg(si_t *sih)
1771 {
1772         if (si_socdevram_size(sih) > 0)
1773                 return TRUE;
1774         else
1775                 return FALSE;
1776 }
1777
1778 uint32
1779 si_socdevram_size(si_t *sih)
1780 {
1781         si_info_t *sii;
1782         uint origidx;
1783         uint intr_val = 0;
1784         uint32 memsize = 0;
1785         sbsocramregs_t *regs;
1786         bool wasup;
1787         uint corerev;
1788
1789         sii = SI_INFO(sih);
1790
1791         /* Block ints and save current core */
1792         INTR_OFF(sii, intr_val);
1793         origidx = si_coreidx(sih);
1794
1795         /* Switch to SOCRAM core */
1796         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1797                 goto done;
1798
1799         /* Get info for determining size */
1800         if (!(wasup = si_iscoreup(sih)))
1801                 si_core_reset(sih, 0, 0);
1802
1803         corerev = si_corerev(sih);
1804         if (corerev >= 10) {
1805                 uint32 extcinfo;
1806                 uint8 nb;
1807                 uint8 i;
1808
1809                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1810                 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1811                 for (i = 0; i < nb; i++)
1812                         memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1813         }
1814
1815         /* Return to previous state and core */
1816         if (!wasup)
1817                 si_core_disable(sih, 0);
1818         si_setcoreidx(sih, origidx);
1819
1820 done:
1821         INTR_RESTORE(sii, intr_val);
1822
1823         return memsize;
1824 }
1825
1826 uint32
1827 si_socdevram_remap_size(si_t *sih)
1828 {
1829         si_info_t *sii;
1830         uint origidx;
1831         uint intr_val = 0;
1832         uint32 memsize = 0, banksz;
1833         sbsocramregs_t *regs;
1834         bool wasup;
1835         uint corerev;
1836         uint32 extcinfo;
1837         uint8 nb;
1838         uint8 i;
1839         uint32 bankidx, bankinfo;
1840
1841         sii = SI_INFO(sih);
1842
1843         /* Block ints and save current core */
1844         INTR_OFF(sii, intr_val);
1845         origidx = si_coreidx(sih);
1846
1847         /* Switch to SOCRAM core */
1848         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1849                 goto done;
1850
1851         /* Get info for determining size */
1852         if (!(wasup = si_iscoreup(sih)))
1853                 si_core_reset(sih, 0, 0);
1854
1855         corerev = si_corerev(sih);
1856         if (corerev >= 16) {
1857                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1858                 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1859
1860                 /*
1861                  * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
1862                  * Only four banks are accessible to ARM
1863                  */
1864                 if ((corerev == 16) && (nb == 5))
1865                         nb = 4;
1866
1867                 for (i = 0; i < nb; i++) {
1868                         bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1869                         W_REG(sii->osh, &regs->bankidx, bankidx);
1870                         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1871                         if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
1872                                 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1873                                 memsize += banksz;
1874                         } else {
1875                                 /* Account only consecutive banks for now */
1876                                 break;
1877                         }
1878                 }
1879         }
1880
1881         /* Return to previous state and core */
1882         if (!wasup)
1883                 si_core_disable(sih, 0);
1884         si_setcoreidx(sih, origidx);
1885
1886 done:
1887         INTR_RESTORE(sii, intr_val);
1888
1889         return memsize;
1890 }
1891
1892 /* Return the RAM size of the SOCRAM core */
1893 uint32
1894 si_socram_size(si_t *sih)
1895 {
1896         si_info_t *sii;
1897         uint origidx;
1898         uint intr_val = 0;
1899
1900         sbsocramregs_t *regs;
1901         bool wasup;
1902         uint corerev;
1903         uint32 coreinfo;
1904         uint memsize = 0;
1905
1906         sii = SI_INFO(sih);
1907
1908         /* Block ints and save current core */
1909         INTR_OFF(sii, intr_val);
1910         origidx = si_coreidx(sih);
1911
1912         /* Switch to SOCRAM core */
1913         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1914                 goto done;
1915
1916         /* Get info for determining size */
1917         if (!(wasup = si_iscoreup(sih)))
1918                 si_core_reset(sih, 0, 0);
1919         corerev = si_corerev(sih);
1920         coreinfo = R_REG(sii->osh, &regs->coreinfo);
1921
1922         /* Calculate size from coreinfo based on rev */
1923         if (corerev == 0)
1924                 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1925         else if (corerev < 3) {
1926                 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1927                 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1928         } else if ((corerev <= 7) || (corerev == 12)) {
1929                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1930                 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1931                 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1932                 if (lss != 0)
1933                         nb --;
1934                 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1935                 if (lss != 0)
1936                         memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1937         } else {
1938                 uint8 i;
1939                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1940                 for (i = 0; i < nb; i++)
1941                         memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1942         }
1943
1944         /* Return to previous state and core */
1945         if (!wasup)
1946                 si_core_disable(sih, 0);
1947         si_setcoreidx(sih, origidx);
1948
1949 done:
1950         INTR_RESTORE(sii, intr_val);
1951
1952         return memsize;
1953 }
1954
1955
1956 /* Return the TCM-RAM size of the ARMCR4 core. */
1957 uint32
1958 si_tcm_size(si_t *sih)
1959 {
1960         si_info_t *sii;
1961         uint origidx;
1962         uint intr_val = 0;
1963         uint8 *regs;
1964         bool wasup;
1965         uint32 corecap;
1966         uint memsize = 0;
1967         uint32 nab = 0;
1968         uint32 nbb = 0;
1969         uint32 totb = 0;
1970         uint32 bxinfo = 0;
1971         uint32 idx = 0;
1972         uint32 *arm_cap_reg;
1973         uint32 *arm_bidx;
1974         uint32 *arm_binfo;
1975
1976         sii = SI_INFO(sih);
1977
1978         /* Block ints and save current core */
1979         INTR_OFF(sii, intr_val);
1980         origidx = si_coreidx(sih);
1981
1982         /* Switch to CR4 core */
1983         if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
1984                 goto done;
1985
1986         /* Get info for determining size. If in reset, come out of reset,
1987          * but remain in halt
1988          */
1989         if (!(wasup = si_iscoreup(sih)))
1990                 si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
1991
1992         arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP);
1993         corecap = R_REG(sii->osh, arm_cap_reg);
1994
1995         nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
1996         nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
1997         totb = nab + nbb;
1998
1999         arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX);
2000         arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO);
2001         for (idx = 0; idx < totb; idx++) {
2002                 W_REG(sii->osh, arm_bidx, idx);
2003
2004                 bxinfo = R_REG(sii->osh, arm_binfo);
2005                 memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
2006         }
2007
2008         /* Return to previous state and core */
2009         if (!wasup)
2010                 si_core_disable(sih, 0);
2011         si_setcoreidx(sih, origidx);
2012
2013 done:
2014         INTR_RESTORE(sii, intr_val);
2015
2016         return memsize;
2017 }
2018
2019 uint32
2020 si_socram_srmem_size(si_t *sih)
2021 {
2022         si_info_t *sii;
2023         uint origidx;
2024         uint intr_val = 0;
2025
2026         sbsocramregs_t *regs;
2027         bool wasup;
2028         uint corerev;
2029         uint32 coreinfo;
2030         uint memsize = 0;
2031
2032         if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) {
2033                 return (32 * 1024);
2034         }
2035
2036         sii = SI_INFO(sih);
2037
2038         /* Block ints and save current core */
2039         INTR_OFF(sii, intr_val);
2040         origidx = si_coreidx(sih);
2041
2042         /* Switch to SOCRAM core */
2043         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2044                 goto done;
2045
2046         /* Get info for determining size */
2047         if (!(wasup = si_iscoreup(sih)))
2048                 si_core_reset(sih, 0, 0);
2049         corerev = si_corerev(sih);
2050         coreinfo = R_REG(sii->osh, &regs->coreinfo);
2051
2052         /* Calculate size from coreinfo based on rev */
2053         if (corerev >= 16) {
2054                 uint8 i;
2055                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2056                 for (i = 0; i < nb; i++) {
2057                         W_REG(sii->osh, &regs->bankidx, i);
2058                         if (R_REG(sii->osh, &regs->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK)
2059                                 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
2060                 }
2061         }
2062
2063         /* Return to previous state and core */
2064         if (!wasup)
2065                 si_core_disable(sih, 0);
2066         si_setcoreidx(sih, origidx);
2067
2068 done:
2069         INTR_RESTORE(sii, intr_val);
2070
2071         return memsize;
2072 }
2073
2074
2075 #if !defined(_CFEZ_) || defined(CFG_WL)
2076 void
2077 si_btcgpiowar(si_t *sih)
2078 {
2079         si_info_t *sii;
2080         uint origidx;
2081         uint intr_val = 0;
2082         chipcregs_t *cc;
2083
2084         sii = SI_INFO(sih);
2085
2086         /* Make sure that there is ChipCommon core present &&
2087          * UART_TX is strapped to 1
2088          */
2089         if (!(sih->cccaps & CC_CAP_UARTGPIO))
2090                 return;
2091
2092         /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
2093         INTR_OFF(sii, intr_val);
2094
2095         origidx = si_coreidx(sih);
2096
2097         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2098         ASSERT(cc != NULL);
2099
2100         W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
2101
2102         /* restore the original index */
2103         si_setcoreidx(sih, origidx);
2104
2105         INTR_RESTORE(sii, intr_val);
2106 }
2107
2108 void
2109 si_chipcontrl_btshd0_4331(si_t *sih, bool on)
2110 {
2111         si_info_t *sii;
2112         chipcregs_t *cc;
2113         uint origidx;
2114         uint32 val;
2115         uint intr_val = 0;
2116
2117         sii = SI_INFO(sih);
2118
2119         INTR_OFF(sii, intr_val);
2120
2121         origidx = si_coreidx(sih);
2122
2123         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2124
2125         val = R_REG(sii->osh, &cc->chipcontrol);
2126
2127         /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
2128         if (on) {
2129                 /* Enable bt_shd0 on gpio4: */
2130                 val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
2131                 W_REG(sii->osh, &cc->chipcontrol, val);
2132         } else {
2133                 val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
2134                 W_REG(sii->osh, &cc->chipcontrol, val);
2135         }
2136
2137         /* restore the original index */
2138         si_setcoreidx(sih, origidx);
2139
2140         INTR_RESTORE(sii, intr_val);
2141 }
2142
2143 void
2144 si_chipcontrl_restore(si_t *sih, uint32 val)
2145 {
2146         si_info_t *sii;
2147         chipcregs_t *cc;
2148         uint origidx;
2149
2150         sii = SI_INFO(sih);
2151         origidx = si_coreidx(sih);
2152         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2153         W_REG(sii->osh, &cc->chipcontrol, val);
2154         si_setcoreidx(sih, origidx);
2155 }
2156
2157 uint32
2158 si_chipcontrl_read(si_t *sih)
2159 {
2160         si_info_t *sii;
2161         chipcregs_t *cc;
2162         uint origidx;
2163         uint32 val;
2164
2165         sii = SI_INFO(sih);
2166         origidx = si_coreidx(sih);
2167         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2168         val = R_REG(sii->osh, &cc->chipcontrol);
2169         si_setcoreidx(sih, origidx);
2170         return val;
2171 }
2172
2173 void
2174 si_chipcontrl_epa4331(si_t *sih, bool on)
2175 {
2176         si_info_t *sii;
2177         chipcregs_t *cc;
2178         uint origidx;
2179         uint32 val;
2180
2181         sii = SI_INFO(sih);
2182         origidx = si_coreidx(sih);
2183
2184         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2185
2186         val = R_REG(sii->osh, &cc->chipcontrol);
2187
2188         if (on) {
2189                 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
2190                         val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2191                         /* Ext PA Controls for 4331 12x9 Package */
2192                         W_REG(sii->osh, &cc->chipcontrol, val);
2193                 } else {
2194                         /* Ext PA Controls for 4331 12x12 Package */
2195                         if (sih->chiprev > 0) {
2196                                 W_REG(sii->osh, &cc->chipcontrol, val |
2197                                       (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
2198                         } else {
2199                                 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
2200                         }
2201                 }
2202         } else {
2203                 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
2204                 W_REG(sii->osh, &cc->chipcontrol, val);
2205         }
2206
2207         si_setcoreidx(sih, origidx);
2208 }
2209
2210 /* switch muxed pins, on: SROM, off: FEMCTRL */
2211 void
2212 si_chipcontrl_srom4360(si_t *sih, bool on)
2213 {
2214         si_info_t *sii;
2215         chipcregs_t *cc;
2216         uint origidx;
2217         uint32 val;
2218
2219         sii = SI_INFO(sih);
2220         origidx = si_coreidx(sih);
2221
2222         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2223
2224         val = R_REG(sii->osh, &cc->chipcontrol);
2225
2226         if (on) {
2227                 val &= ~(CCTRL4360_SECI_MODE |
2228                         CCTRL4360_BTSWCTRL_MODE |
2229                         CCTRL4360_EXTRA_FEMCTRL_MODE |
2230                         CCTRL4360_BT_LGCY_MODE |
2231                         CCTRL4360_CORE2FEMCTRL4_ON);
2232
2233                 W_REG(sii->osh, &cc->chipcontrol, val);
2234         } else {
2235         }
2236
2237         si_setcoreidx(sih, origidx);
2238 }
2239
2240 void
2241 si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
2242 {
2243         si_info_t *sii;
2244         chipcregs_t *cc;
2245         uint origidx;
2246         uint32 val;
2247         bool sel_chip;
2248
2249         sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
2250                 (CHIPID(sih->chip) == BCM43431_CHIP_ID);
2251         sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
2252
2253         if (!sel_chip)
2254                 return;
2255
2256         sii = SI_INFO(sih);
2257         origidx = si_coreidx(sih);
2258
2259         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2260
2261         val = R_REG(sii->osh, &cc->chipcontrol);
2262
2263         if (enter_wowl) {
2264                 val |= CCTRL4331_EXTPA_EN;
2265                 W_REG(sii->osh, &cc->chipcontrol, val);
2266         } else {
2267                 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2268                 W_REG(sii->osh, &cc->chipcontrol, val);
2269         }
2270         si_setcoreidx(sih, origidx);
2271 }
2272 #endif 
2273
2274 uint
2275 si_pll_reset(si_t *sih)
2276 {
2277         uint err = 0;
2278
2279         return (err);
2280 }
2281
2282 /* Enable BT-COEX & Ex-PA for 4313 */
2283 void
2284 si_epa_4313war(si_t *sih)
2285 {
2286         si_info_t *sii;
2287         chipcregs_t *cc;
2288         uint origidx;
2289
2290         sii = SI_INFO(sih);
2291         origidx = si_coreidx(sih);
2292
2293         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2294
2295         /* EPA Fix */
2296         W_REG(sii->osh, &cc->gpiocontrol,
2297                 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2298
2299         si_setcoreidx(sih, origidx);
2300 }
2301
2302 void
2303 si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
2304 {
2305 }
2306
2307 /* Re-enable synth_pwrsw resource in min_res_mask for 4313 */
2308 void
2309 si_pmu_synth_pwrsw_4313_war(si_t *sih)
2310 {
2311 }
2312
2313 /* WL/BT control for 4313 btcombo boards >= P250 */
2314 void
2315 si_btcombo_p250_4313_war(si_t *sih)
2316 {
2317         si_info_t *sii;
2318         chipcregs_t *cc;
2319         uint origidx;
2320
2321         sii = SI_INFO(sih);
2322         origidx = si_coreidx(sih);
2323
2324         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2325         W_REG(sii->osh, &cc->gpiocontrol,
2326                 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
2327
2328         W_REG(sii->osh, &cc->gpioouten,
2329                 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
2330
2331         si_setcoreidx(sih, origidx);
2332 }
2333 void
2334 si_btc_enable_chipcontrol(si_t *sih)
2335 {
2336         si_info_t *sii;
2337         chipcregs_t *cc;
2338         uint origidx;
2339
2340         sii = SI_INFO(sih);
2341         origidx = si_coreidx(sih);
2342
2343         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2344
2345         /* BT fix */
2346         W_REG(sii->osh, &cc->chipcontrol,
2347                 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
2348
2349         si_setcoreidx(sih, origidx);
2350 }
2351 void
2352 si_btcombo_43228_war(si_t *sih)
2353 {
2354         si_info_t *sii;
2355         chipcregs_t *cc;
2356         uint origidx;
2357
2358         sii = SI_INFO(sih);
2359         origidx = si_coreidx(sih);
2360
2361         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2362
2363         W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
2364         W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
2365
2366         si_setcoreidx(sih, origidx);
2367 }
2368
2369 /* check if the device is removed */
2370 bool
2371 si_deviceremoved(si_t *sih)
2372 {
2373         uint32 w;
2374         si_info_t *sii;
2375
2376         sii = SI_INFO(sih);
2377
2378         switch (BUSTYPE(sih->bustype)) {
2379         case PCI_BUS:
2380                 ASSERT(sii->osh != NULL);
2381                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
2382                 if ((w & 0xFFFF) != VENDOR_BROADCOM)
2383                         return TRUE;
2384                 break;
2385         }
2386         return FALSE;
2387 }
2388
2389 bool
2390 si_is_sprom_available(si_t *sih)
2391 {
2392         if (sih->ccrev >= 31) {
2393                 si_info_t *sii;
2394                 uint origidx;
2395                 chipcregs_t *cc;
2396                 uint32 sromctrl;
2397
2398                 if ((sih->cccaps & CC_CAP_SROM) == 0)
2399                         return FALSE;
2400
2401                 sii = SI_INFO(sih);
2402                 origidx = sii->curidx;
2403                 cc = si_setcoreidx(sih, SI_CC_IDX);
2404                 ASSERT(cc);
2405                 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
2406                 si_setcoreidx(sih, origidx);
2407                 return (sromctrl & SRC_PRESENT);
2408         }
2409
2410         switch (CHIPID(sih->chip)) {
2411         case BCM4312_CHIP_ID:
2412                 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
2413         case BCM4325_CHIP_ID:
2414                 return (sih->chipst & CST4325_SPROM_SEL) != 0;
2415         case BCM4322_CHIP_ID:   case BCM43221_CHIP_ID:  case BCM43231_CHIP_ID:
2416         case BCM43222_CHIP_ID:  case BCM43111_CHIP_ID:  case BCM43112_CHIP_ID:
2417         case BCM4342_CHIP_ID: {
2418                 uint32 spromotp;
2419                 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
2420                         CST4322_SPROM_OTP_SEL_SHIFT;
2421                 return (spromotp & CST4322_SPROM_PRESENT) != 0;
2422         }
2423         case BCM4329_CHIP_ID:
2424                 return (sih->chipst & CST4329_SPROM_SEL) != 0;
2425         case BCM4315_CHIP_ID:
2426                 return (sih->chipst & CST4315_SPROM_SEL) != 0;
2427         case BCM4319_CHIP_ID:
2428                 return (sih->chipst & CST4319_SPROM_SEL) != 0;
2429         case BCM4336_CHIP_ID:
2430         case BCM43362_CHIP_ID:
2431                 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
2432         case BCM4330_CHIP_ID:
2433                 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
2434         case BCM4313_CHIP_ID:
2435                 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
2436         case BCM4331_CHIP_ID:
2437         case BCM43431_CHIP_ID:
2438                 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
2439         case BCM43239_CHIP_ID:
2440                 return ((sih->chipst & CST43239_SPROM_MASK) &&
2441                         !(sih->chipst & CST43239_SFLASH_MASK));
2442         case BCM4324_CHIP_ID:
2443         case BCM43242_CHIP_ID:
2444                 return ((sih->chipst & CST4324_SPROM_MASK) &&
2445                         !(sih->chipst & CST4324_SFLASH_MASK));
2446         case BCM4335_CHIP_ID:
2447                 return ((sih->chipst & CST4335_SPROM_MASK) &&
2448                         !(sih->chipst & CST4335_SFLASH_MASK));
2449         case BCM4350_CHIP_ID:
2450                 return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
2451         case BCM43131_CHIP_ID:
2452         case BCM43217_CHIP_ID:
2453         case BCM43227_CHIP_ID:
2454         case BCM43228_CHIP_ID:
2455         case BCM43428_CHIP_ID:
2456                 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
2457         default:
2458                 return TRUE;
2459         }
2460 }
2461
2462
2463 uint32 si_get_sromctl(si_t *sih)
2464 {
2465         chipcregs_t *cc;
2466         uint origidx;
2467         uint32 sromctl;
2468         osl_t *osh;
2469
2470         osh = si_osh(sih);
2471         origidx = si_coreidx(sih);
2472         cc = si_setcoreidx(sih, SI_CC_IDX);
2473         ASSERT((uintptr)cc);
2474
2475         sromctl = R_REG(osh, &cc->sromcontrol);
2476
2477         /* return to the original core */
2478         si_setcoreidx(sih, origidx);
2479         return sromctl;
2480 }
2481
2482 int si_set_sromctl(si_t *sih, uint32 value)
2483 {
2484         chipcregs_t *cc;
2485         uint origidx;
2486         osl_t *osh;
2487
2488         osh = si_osh(sih);
2489         origidx = si_coreidx(sih);
2490         cc = si_setcoreidx(sih, SI_CC_IDX);
2491         ASSERT((uintptr)cc);
2492
2493         /* get chipcommon rev */
2494         if (si_corerev(sih) < 32)
2495                 return BCME_UNSUPPORTED;
2496
2497         W_REG(osh, &cc->sromcontrol, value);
2498
2499         /* return to the original core */
2500         si_setcoreidx(sih, origidx);
2501         return BCME_OK;
2502
2503 }
2504
2505 uint
2506 si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val)
2507 {
2508         uint origidx;
2509         uint ret_val;
2510
2511         origidx = si_coreidx(sih);
2512
2513         si_setcoreidx(sih, coreidx);
2514
2515         ret_val = si_wrapperreg(sih, offset, mask, val);
2516
2517         /* return to the original core */
2518         si_setcoreidx(sih, origidx);
2519         return ret_val;
2520 }