upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / net / wireless / bcm4330 / src / shared / siutils.c
1 /*
2  * Misc utility routines for accessing chip-specific features
3  * of the SiliconBackplane-based Broadcom chips.
4  *
5  * Copyright (C) 1999-2011, Broadcom Corporation
6  * 
7  *         Unless you and Broadcom execute a separate written software license
8  * agreement governing use of this software, this software is licensed to you
9  * under the terms of the GNU General Public License version 2 (the "GPL"),
10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11  * following added to such license:
12  * 
13  *      As a special exception, the copyright holders of this software give you
14  * permission to link this software with independent modules, and to copy and
15  * distribute the resulting executable under terms of your choice, provided that
16  * you also meet, for each linked independent module, the terms and conditions of
17  * the license of that module.  An independent module is a module which is not
18  * derived from this software.  The special exception does not apply to any
19  * modifications of the software.
20  * 
21  *      Notwithstanding the above, under no circumstances may you combine this
22  * software in any way with any other Broadcom software provided under a license
23  * other than the GPL, without Broadcom's express prior written consent.
24  *
25  * $Id: siutils.c,v 1.813.2.33 2011-01-13 19:11:51 $
26  */
27
28 #include <typedefs.h>
29 #include <bcmdefs.h>
30 #include <osl.h>
31 #include <bcmutils.h>
32 #include <siutils.h>
33 #include <bcmdevs.h>
34 #include <hndsoc.h>
35 #include <sbchipc.h>
36 #include <pcicfg.h>
37 #include <sbpcmcia.h>
38 #include <sbsocram.h>
39 #include <bcmsdh.h>
40 #include <sdio.h>
41 #include <sbsdio.h>
42 #include <sbhnddma.h>
43 #include <sbsdpcmdev.h>
44 #include <bcmsdpcm.h>
45 #include <hndpmu.h>
46 #ifdef BCMSPI
47 #include <spid.h>
48 #endif /* BCMSPI */
49
50 #include "siutils_priv.h"
51
52 /* local prototypes */
53 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
54                               uint bustype, void *sdh, char **vars, uint *varsz);
55 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
56 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
57         uint *origidx, void *regs);
58
59
60 /* global variable to indicate reservation/release of gpio's */
61 static uint32 si_gpioreservation = 0;
62
63 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
64
65 /*
66  * Allocate a si handle.
67  * devid - pci device id (used to determine chip#)
68  * osh - opaque OS handle
69  * regs - virtual address of initial core registers
70  * bustype - pci/pcmcia/sb/sdio/etc
71  * vars - pointer to a pointer area for "environment" variables
72  * varsz - pointer to int to return the size of the vars
73  */
74 si_t *
75 si_attach(uint devid, osl_t *osh, void *regs,
76                        uint bustype, void *sdh, char **vars, uint *varsz)
77 {
78         si_info_t *sii;
79
80         /* alloc si_info_t */
81         if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
82                 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
83                 return (NULL);
84         }
85
86         if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
87                 MFREE(osh, sii, sizeof(si_info_t));
88                 return (NULL);
89         }
90         sii->vars = vars ? *vars : NULL;
91         sii->varsz = varsz ? *varsz : 0;
92
93         return (si_t *)sii;
94 }
95
96 /* global kernel resource */
97 static si_info_t ksii;
98
99 static uint32   wd_msticks;             /* watchdog timer ticks normalized to ms */
100
101 /* generic kernel variant of si_attach() */
102 si_t *
103 si_kattach(osl_t *osh)
104 {
105         static bool ksii_attached = FALSE;
106
107         if (!ksii_attached) {
108                 void *regs;
109                 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
110
111                 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
112                                 SI_BUS, NULL,
113                                 osh != SI_OSH ? &ksii.vars : NULL,
114                                 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
115                         SI_ERROR(("si_kattach: si_doattach failed\n"));
116                         REG_UNMAP(regs);
117                         return NULL;
118                 }
119                 REG_UNMAP(regs);
120
121                 /* save ticks normalized to ms for si_watchdog_ms() */
122                 if (PMUCTL_ENAB(&ksii.pub)) {
123                         /* based on 32KHz ILP clock */
124                         wd_msticks = 32;
125                 } else {
126                         wd_msticks = ALP_CLOCK / 1000;
127                 }
128
129                 ksii_attached = TRUE;
130                 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
131                         ksii.pub.ccrev, wd_msticks));
132         }
133
134         return &ksii.pub;
135 }
136
137
138 static bool
139 si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
140 {
141         /* need to set memseg flag for CF card first before any sb registers access */
142         if (BUSTYPE(bustype) == PCMCIA_BUS)
143                 sii->memseg = TRUE;
144
145
146         if (BUSTYPE(bustype) == SDIO_BUS) {
147                 int err;
148                 uint8 clkset;
149
150                 /* Try forcing SDIO core to do ALPAvail request only */
151                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
152                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
153                 if (!err) {
154                         uint8 clkval;
155
156                         /* If register supported, wait for ALPAvail and then force ALP */
157                         clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
158                         if ((clkval & ~SBSDIO_AVBITS) == clkset) {
159                                 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
160                                         SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
161                                         PMU_MAX_TRANSITION_DLY);
162                                 if (!SBSDIO_ALPAV(clkval)) {
163                                         SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
164                                                 clkval));
165                                         return FALSE;
166                                 }
167                                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
168                                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
169                                         clkset, &err);
170                                 OSL_DELAY(65);
171                         }
172                 }
173
174                 /* Also, disable the extra SDIO pull-ups */
175                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
176         }
177
178 #ifdef BCMSPI
179         /* Avoid backplane accesses before wake-wlan (i.e. htavail) for spi.
180          * F1 read accesses may return correct data but with data-not-available dstatus bit set.
181          */
182         if (BUSTYPE(bustype) == SPI_BUS) {
183
184                 int err;
185                 uint32 regdata;
186                 /* wake up wlan function :WAKE_UP goes as HT_AVAIL request in hardware */
187                 regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
188                 SI_MSG(("F0 REG0 rd = 0x%x\n", regdata));
189                 regdata |= WAKE_UP;
190
191                 bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
192
193                 OSL_DELAY(100000);
194         }
195 #endif /* BCMSPI */
196
197         return TRUE;
198 }
199
200 static bool
201 si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
202         uint *origidx, void *regs)
203 {
204         bool pci, pcie;
205         uint i;
206         uint pciidx, pcieidx, pcirev, pcierev;
207
208         cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
209         ASSERT((uintptr)cc);
210
211         /* get chipcommon rev */
212         sii->pub.ccrev = (int)si_corerev(&sii->pub);
213
214         /* get chipcommon chipstatus */
215         if (sii->pub.ccrev >= 11)
216                 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
217
218         /* get chipcommon capabilites */
219         sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
220         /* get chipcommon extended capabilities */
221
222         if (sii->pub.ccrev >= 35)
223                 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
224
225         /* get pmu rev and caps */
226         if (sii->pub.cccaps & CC_CAP_PMU) {
227                 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
228                 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
229         }
230
231         SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
232                 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
233                 sii->pub.pmucaps));
234
235         /* figure out bus/orignal core idx */
236         sii->pub.buscoretype = NODEV_CORE_ID;
237         sii->pub.buscorerev = NOREV;
238         sii->pub.buscoreidx = BADIDX;
239
240         pci = pcie = FALSE;
241         pcirev = pcierev = NOREV;
242         pciidx = pcieidx = BADIDX;
243
244         for (i = 0; i < sii->numcores; i++) {
245                 uint cid, crev;
246
247                 si_setcoreidx(&sii->pub, i);
248                 cid = si_coreid(&sii->pub);
249                 crev = si_corerev(&sii->pub);
250
251                 /* Display cores found */
252                 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
253                         i, cid, crev, sii->coresba[i], sii->regs[i]));
254
255                 if (BUSTYPE(bustype) == PCI_BUS) {
256                         if (cid == PCI_CORE_ID) {
257                                 pciidx = i;
258                                 pcirev = crev;
259                                 pci = TRUE;
260                         } else if (cid == PCIE_CORE_ID) {
261                                 pcieidx = i;
262                                 pcierev = crev;
263                                 pcie = TRUE;
264                         }
265                 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
266                            (cid == PCMCIA_CORE_ID)) {
267                         sii->pub.buscorerev = crev;
268                         sii->pub.buscoretype = cid;
269                         sii->pub.buscoreidx = i;
270                 }
271                 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
272                           (BUSTYPE(bustype) == SPI_BUS)) &&
273                          ((cid == PCMCIA_CORE_ID) ||
274                           (cid == SDIOD_CORE_ID))) {
275                         sii->pub.buscorerev = crev;
276                         sii->pub.buscoretype = cid;
277                         sii->pub.buscoreidx = i;
278                 }
279
280                 /* find the core idx before entering this func. */
281                 if ((savewin && (savewin == sii->coresba[i])) ||
282                     (regs == sii->regs[i]))
283                         *origidx = i;
284         }
285
286         if (pci) {
287                 sii->pub.buscoretype = PCI_CORE_ID;
288                 sii->pub.buscorerev = pcirev;
289                 sii->pub.buscoreidx = pciidx;
290         } else if (pcie) {
291                 sii->pub.buscoretype = PCIE_CORE_ID;
292                 sii->pub.buscorerev = pcierev;
293                 sii->pub.buscoreidx = pcieidx;
294         }
295
296         SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
297                  sii->pub.buscorerev));
298
299         if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
300             (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
301                 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
302
303
304         /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
305          * already running.
306          */
307         if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
308                 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
309                     si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
310                         si_core_disable(&sii->pub, 0);
311         }
312
313         /* return to the original core */
314         si_setcoreidx(&sii->pub, *origidx);
315
316         return TRUE;
317 }
318
319
320
321 static si_info_t *
322 si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
323                        uint bustype, void *sdh, char **vars, uint *varsz)
324 {
325         struct si_pub *sih = &sii->pub;
326         uint32 w, savewin;
327         chipcregs_t *cc;
328         char *pvars = NULL;
329         uint origidx;
330
331         ASSERT(GOODREGS(regs));
332
333         bzero((uchar*)sii, sizeof(si_info_t));
334
335         savewin = 0;
336
337         sih->buscoreidx = BADIDX;
338
339         sii->curmap = regs;
340         sii->sdh = sdh;
341         sii->osh = osh;
342
343
344
345         /* find Chipcommon address */
346         if (bustype == PCI_BUS) {
347                 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
348                 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
349                         savewin = SI_ENUM_BASE;
350                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
351                 cc = (chipcregs_t *)regs;
352         } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
353                 cc = (chipcregs_t *)sii->curmap;
354         } else {
355                 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
356         }
357
358         sih->bustype = bustype;
359         if (bustype != BUSTYPE(bustype)) {
360                 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
361                         bustype, BUSTYPE(bustype)));
362                 return NULL;
363         }
364
365         /* bus/core/clk setup for register access */
366         if (!si_buscore_prep(sii, bustype, devid, sdh)) {
367                 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
368                 return NULL;
369         }
370
371         /* ChipID recognition.
372          *   We assume we can read chipid at offset 0 from the regs arg.
373          *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
374          *   some way of recognizing them needs to be added here.
375          */
376         w = R_REG(osh, &cc->chipid);
377         sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
378         /* Might as wll fill in chip id rev & pkg */
379         sih->chip = w & CID_ID_MASK;
380         sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
381         sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
382         if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
383                 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
384                 CST4322_SPROM_PRESENT))) {
385                 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
386                 return NULL;
387         }
388
389         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
390                 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
391                 sih->chippkg = BCM4329_182PIN_PKG_ID;
392         }
393
394         sih->issim = IS_SIM(sih->chippkg);
395
396         /* scan for cores */
397         if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
398                 SI_MSG(("Found chip type SB (0x%08x)\n", w));
399                 sb_scan(&sii->pub, regs, devid);
400         } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
401                 SI_MSG(("Found chip type AI (0x%08x)\n", w));
402                 /* pass chipc address instead of original core base */
403                 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
404         } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
405                 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
406                 /* pass chipc address instead of original core base */
407                 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
408         } else {
409                 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
410                 return NULL;
411         }
412         /* no cores found, bail out */
413         if (sii->numcores == 0) {
414                 SI_ERROR(("si_doattach: could not find any cores\n"));
415                 return NULL;
416         }
417         /* bus/core/clk setup */
418         origidx = SI_CC_IDX;
419         if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
420                 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
421                 goto exit;
422         }
423
424         /* assume current core is CC */
425         if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
426                                           CHIPID(sih->chip) == BCM43235_CHIP_ID ||
427                                           CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
428                                          (CHIPREV(sii->pub.chiprev) == 0))) {
429
430                 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
431                         uint clkdiv;
432                         clkdiv = R_REG(osh, &cc->clkdiv);
433                         /* otp_clk_div is even number, 120/14 < 9mhz */
434                         clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
435                         W_REG(osh, &cc->clkdiv, clkdiv);
436                         SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
437                 }
438                 OSL_DELAY(10);
439         }
440
441
442         pvars = NULL;
443
444
445
446                 if (sii->pub.ccrev >= 20) {
447                         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
448                         ASSERT(cc != NULL);
449                         W_REG(osh, &cc->gpiopullup, 0);
450                         W_REG(osh, &cc->gpiopulldown, 0);
451                         si_setcoreidx(sih, origidx);
452                 }
453
454
455
456
457         return (sii);
458
459 exit:
460
461         return NULL;
462 }
463
464 /* may be called with core in reset */
465 void
466 si_detach(si_t *sih)
467 {
468         si_info_t *sii;
469         uint idx;
470
471
472         sii = SI_INFO(sih);
473
474         if (sii == NULL)
475                 return;
476
477         if (BUSTYPE(sih->bustype) == SI_BUS)
478                 for (idx = 0; idx < SI_MAXCORES; idx++)
479                         if (sii->regs[idx]) {
480                                 REG_UNMAP(sii->regs[idx]);
481                                 sii->regs[idx] = NULL;
482                         }
483
484
485
486 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
487         if (sii != &ksii)
488 #endif  /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
489                 MFREE(sii->osh, sii, sizeof(si_info_t));
490 }
491
492 void *
493 si_osh(si_t *sih)
494 {
495         si_info_t *sii;
496
497         sii = SI_INFO(sih);
498         return sii->osh;
499 }
500
501 void
502 si_setosh(si_t *sih, osl_t *osh)
503 {
504         si_info_t *sii;
505
506         sii = SI_INFO(sih);
507         if (sii->osh != NULL) {
508                 SI_ERROR(("osh is already set....\n"));
509                 ASSERT(!sii->osh);
510         }
511         sii->osh = osh;
512 }
513
514 /* register driver interrupt disabling and restoring callback functions */
515 void
516 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
517                           void *intrsenabled_fn, void *intr_arg)
518 {
519         si_info_t *sii;
520
521         sii = SI_INFO(sih);
522         sii->intr_arg = intr_arg;
523         sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
524         sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
525         sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
526         /* save current core id.  when this function called, the current core
527          * must be the core which provides driver functions(il, et, wl, etc.)
528          */
529         sii->dev_coreid = sii->coreid[sii->curidx];
530 }
531
532 void
533 si_deregister_intr_callback(si_t *sih)
534 {
535         si_info_t *sii;
536
537         sii = SI_INFO(sih);
538         sii->intrsoff_fn = NULL;
539 }
540
541 uint
542 si_intflag(si_t *sih)
543 {
544         si_info_t *sii = SI_INFO(sih);
545
546         if (CHIPTYPE(sih->socitype) == SOCI_SB)
547                 return sb_intflag(sih);
548         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
549                 return R_REG(sii->osh, ((uint32 *)(uintptr)
550                             (sii->oob_router + OOB_STATUSA)));
551         else {
552                 ASSERT(0);
553                 return 0;
554         }
555 }
556
557 uint
558 si_flag(si_t *sih)
559 {
560         if (CHIPTYPE(sih->socitype) == SOCI_SB)
561                 return sb_flag(sih);
562         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
563                 return ai_flag(sih);
564         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
565                 return ub_flag(sih);
566         else {
567                 ASSERT(0);
568                 return 0;
569         }
570 }
571
572 void
573 si_setint(si_t *sih, int siflag)
574 {
575         if (CHIPTYPE(sih->socitype) == SOCI_SB)
576                 sb_setint(sih, siflag);
577         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
578                 ai_setint(sih, siflag);
579         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
580                 ub_setint(sih, siflag);
581         else
582                 ASSERT(0);
583 }
584
585 uint
586 si_coreid(si_t *sih)
587 {
588         si_info_t *sii;
589
590         sii = SI_INFO(sih);
591         return sii->coreid[sii->curidx];
592 }
593
594 uint
595 si_coreidx(si_t *sih)
596 {
597         si_info_t *sii;
598
599         sii = SI_INFO(sih);
600         return sii->curidx;
601 }
602
603 /* return the core-type instantiation # of the current core */
604 uint
605 si_coreunit(si_t *sih)
606 {
607         si_info_t *sii;
608         uint idx;
609         uint coreid;
610         uint coreunit;
611         uint i;
612
613         sii = SI_INFO(sih);
614         coreunit = 0;
615
616         idx = sii->curidx;
617
618         ASSERT(GOODREGS(sii->curmap));
619         coreid = si_coreid(sih);
620
621         /* count the cores of our type */
622         for (i = 0; i < idx; i++)
623                 if (sii->coreid[i] == coreid)
624                         coreunit++;
625
626         return (coreunit);
627 }
628
629 uint
630 si_corevendor(si_t *sih)
631 {
632         if (CHIPTYPE(sih->socitype) == SOCI_SB)
633                 return sb_corevendor(sih);
634         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
635                 return ai_corevendor(sih);
636         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
637                 return ub_corevendor(sih);
638         else {
639                 ASSERT(0);
640                 return 0;
641         }
642 }
643
644 bool
645 si_backplane64(si_t *sih)
646 {
647         return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
648 }
649
650 uint
651 si_corerev(si_t *sih)
652 {
653         if (CHIPTYPE(sih->socitype) == SOCI_SB)
654                 return sb_corerev(sih);
655         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
656                 return ai_corerev(sih);
657         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
658                 return ub_corerev(sih);
659         else {
660                 ASSERT(0);
661                 return 0;
662         }
663 }
664
665 /* return index of coreid or BADIDX if not found */
666 uint
667 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
668 {
669         si_info_t *sii;
670         uint found;
671         uint i;
672
673         sii = SI_INFO(sih);
674
675         found = 0;
676
677         for (i = 0; i < sii->numcores; i++)
678                 if (sii->coreid[i] == coreid) {
679                         if (found == coreunit)
680                                 return (i);
681                         found++;
682                 }
683
684         return (BADIDX);
685 }
686
687 /* return list of found cores */
688 uint
689 si_corelist(si_t *sih, uint coreid[])
690 {
691         si_info_t *sii;
692
693         sii = SI_INFO(sih);
694
695         bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
696         return (sii->numcores);
697 }
698
699 /* return current register mapping */
700 void *
701 si_coreregs(si_t *sih)
702 {
703         si_info_t *sii;
704
705         sii = SI_INFO(sih);
706         ASSERT(GOODREGS(sii->curmap));
707
708         return (sii->curmap);
709 }
710
711 /*
712  * This function changes logical "focus" to the indicated core;
713  * must be called with interrupts off.
714  * Moreover, callers should keep interrupts off during switching out of and back to d11 core
715  */
716 void *
717 si_setcore(si_t *sih, uint coreid, uint coreunit)
718 {
719         uint idx;
720
721         idx = si_findcoreidx(sih, coreid, coreunit);
722         if (!GOODIDX(idx))
723                 return (NULL);
724
725         if (CHIPTYPE(sih->socitype) == SOCI_SB)
726                 return sb_setcoreidx(sih, idx);
727         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
728                 return ai_setcoreidx(sih, idx);
729         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
730                 return ub_setcoreidx(sih, idx);
731         else {
732                 ASSERT(0);
733                 return NULL;
734         }
735 }
736
737 void *
738 si_setcoreidx(si_t *sih, uint coreidx)
739 {
740         if (CHIPTYPE(sih->socitype) == SOCI_SB)
741                 return sb_setcoreidx(sih, coreidx);
742         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
743                 return ai_setcoreidx(sih, coreidx);
744         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
745                 return ub_setcoreidx(sih, coreidx);
746         else {
747                 ASSERT(0);
748                 return NULL;
749         }
750 }
751
752 /* Turn off interrupt as required by sb_setcore, before switch core */
753 void *
754 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
755 {
756         void *cc;
757         si_info_t *sii;
758
759         sii = SI_INFO(sih);
760
761         if (SI_FAST(sii)) {
762                 /* Overloading the origidx variable to remember the coreid,
763                  * this works because the core ids cannot be confused with
764                  * core indices.
765                  */
766                 *origidx = coreid;
767                 if (coreid == CC_CORE_ID)
768                         return (void *)CCREGS_FAST(sii);
769                 else if (coreid == sih->buscoretype)
770                         return (void *)PCIEREGS(sii);
771         }
772         INTR_OFF(sii, *intr_val);
773         *origidx = sii->curidx;
774         cc = si_setcore(sih, coreid, 0);
775         ASSERT(cc != NULL);
776
777         return cc;
778 }
779
780 /* restore coreidx and restore interrupt */
781 void
782 si_restore_core(si_t *sih, uint coreid, uint intr_val)
783 {
784         si_info_t *sii;
785
786         sii = SI_INFO(sih);
787         if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
788                 return;
789
790         si_setcoreidx(sih, coreid);
791         INTR_RESTORE(sii, intr_val);
792 }
793
794 int
795 si_numaddrspaces(si_t *sih)
796 {
797         if (CHIPTYPE(sih->socitype) == SOCI_SB)
798                 return sb_numaddrspaces(sih);
799         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
800                 return ai_numaddrspaces(sih);
801         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
802                 return ub_numaddrspaces(sih);
803         else {
804                 ASSERT(0);
805                 return 0;
806         }
807 }
808
809 uint32
810 si_addrspace(si_t *sih, uint asidx)
811 {
812         if (CHIPTYPE(sih->socitype) == SOCI_SB)
813                 return sb_addrspace(sih, asidx);
814         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
815                 return ai_addrspace(sih, asidx);
816         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
817                 return ub_addrspace(sih, asidx);
818         else {
819                 ASSERT(0);
820                 return 0;
821         }
822 }
823
824 uint32
825 si_addrspacesize(si_t *sih, uint asidx)
826 {
827         if (CHIPTYPE(sih->socitype) == SOCI_SB)
828                 return sb_addrspacesize(sih, asidx);
829         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
830                 return ai_addrspacesize(sih, asidx);
831         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
832                 return ub_addrspacesize(sih, asidx);
833         else {
834                 ASSERT(0);
835                 return 0;
836         }
837 }
838
839 uint32
840 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
841 {
842         if (CHIPTYPE(sih->socitype) == SOCI_SB)
843                 return sb_core_cflags(sih, mask, val);
844         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
845                 return ai_core_cflags(sih, mask, val);
846         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
847                 return ub_core_cflags(sih, mask, val);
848         else {
849                 ASSERT(0);
850                 return 0;
851         }
852 }
853
854 void
855 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
856 {
857         if (CHIPTYPE(sih->socitype) == SOCI_SB)
858                 sb_core_cflags_wo(sih, mask, val);
859         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
860                 ai_core_cflags_wo(sih, mask, val);
861         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
862                 ub_core_cflags_wo(sih, mask, val);
863         else
864                 ASSERT(0);
865 }
866
867 uint32
868 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
869 {
870         if (CHIPTYPE(sih->socitype) == SOCI_SB)
871                 return sb_core_sflags(sih, mask, val);
872         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
873                 return ai_core_sflags(sih, mask, val);
874         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
875                 return ub_core_sflags(sih, mask, val);
876         else {
877                 ASSERT(0);
878                 return 0;
879         }
880 }
881
882 bool
883 si_iscoreup(si_t *sih)
884 {
885         if (CHIPTYPE(sih->socitype) == SOCI_SB)
886                 return sb_iscoreup(sih);
887         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
888                 return ai_iscoreup(sih);
889         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
890                 return ub_iscoreup(sih);
891         else {
892                 ASSERT(0);
893                 return FALSE;
894         }
895 }
896
897 uint
898 si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
899 {
900         /* only for AI back plane chips */
901         if (CHIPTYPE(sih->socitype) == SOCI_AI)
902                 return (ai_wrap_reg(sih, offset, mask, val));
903         return 0;
904 }
905
906 uint
907 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
908 {
909         if (CHIPTYPE(sih->socitype) == SOCI_SB)
910                 return sb_corereg(sih, coreidx, regoff, mask, val);
911         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
912                 return ai_corereg(sih, coreidx, regoff, mask, val);
913         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
914                 return ub_corereg(sih, coreidx, regoff, mask, val);
915         else {
916                 ASSERT(0);
917                 return 0;
918         }
919 }
920
921 void
922 si_core_disable(si_t *sih, uint32 bits)
923 {
924         if (CHIPTYPE(sih->socitype) == SOCI_SB)
925                 sb_core_disable(sih, bits);
926         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
927                 ai_core_disable(sih, bits);
928         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
929                 ub_core_disable(sih, bits);
930 }
931
932 void
933 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
934 {
935         if (CHIPTYPE(sih->socitype) == SOCI_SB)
936                 sb_core_reset(sih, bits, resetbits);
937         else if (CHIPTYPE(sih->socitype) == SOCI_AI)
938                 ai_core_reset(sih, bits, resetbits);
939         else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
940                 ub_core_reset(sih, bits, resetbits);
941 }
942
943 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
944 int
945 si_corebist(si_t *sih)
946 {
947         uint32 cflags;
948         int result = 0;
949
950         /* Read core control flags */
951         cflags = si_core_cflags(sih, 0, 0);
952
953         /* Set bist & fgc */
954         si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
955
956         /* Wait for bist done */
957         SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
958
959         if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
960                 result = BCME_ERROR;
961
962         /* Reset core control flags */
963         si_core_cflags(sih, 0xffff, cflags);
964
965         return result;
966 }
967
968 static uint32
969 factor6(uint32 x)
970 {
971         switch (x) {
972         case CC_F6_2:   return 2;
973         case CC_F6_3:   return 3;
974         case CC_F6_4:   return 4;
975         case CC_F6_5:   return 5;
976         case CC_F6_6:   return 6;
977         case CC_F6_7:   return 7;
978         default:        return 0;
979         }
980 }
981
982 /* calculate the speed the SI would run at given a set of clockcontrol values */
983 uint32
984 si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
985 {
986         uint32 n1, n2, clock, m1, m2, m3, mc;
987
988         n1 = n & CN_N1_MASK;
989         n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
990
991         if (pll_type == PLL_TYPE6) {
992                 if (m & CC_T6_MMASK)
993                         return CC_T6_M1;
994                 else
995                         return CC_T6_M0;
996         } else if ((pll_type == PLL_TYPE1) ||
997                    (pll_type == PLL_TYPE3) ||
998                    (pll_type == PLL_TYPE4) ||
999                    (pll_type == PLL_TYPE7)) {
1000                 n1 = factor6(n1);
1001                 n2 += CC_F5_BIAS;
1002         } else if (pll_type == PLL_TYPE2) {
1003                 n1 += CC_T2_BIAS;
1004                 n2 += CC_T2_BIAS;
1005                 ASSERT((n1 >= 2) && (n1 <= 7));
1006                 ASSERT((n2 >= 5) && (n2 <= 23));
1007         } else if (pll_type == PLL_TYPE5) {
1008                 return (100000000);
1009         } else
1010                 ASSERT(0);
1011         /* PLL types 3 and 7 use BASE2 (25Mhz) */
1012         if ((pll_type == PLL_TYPE3) ||
1013             (pll_type == PLL_TYPE7)) {
1014                 clock = CC_CLOCK_BASE2 * n1 * n2;
1015         } else
1016                 clock = CC_CLOCK_BASE1 * n1 * n2;
1017
1018         if (clock == 0)
1019                 return 0;
1020
1021         m1 = m & CC_M1_MASK;
1022         m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1023         m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1024         mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1025
1026         if ((pll_type == PLL_TYPE1) ||
1027             (pll_type == PLL_TYPE3) ||
1028             (pll_type == PLL_TYPE4) ||
1029             (pll_type == PLL_TYPE7)) {
1030                 m1 = factor6(m1);
1031                 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1032                         m2 += CC_F5_BIAS;
1033                 else
1034                         m2 = factor6(m2);
1035                 m3 = factor6(m3);
1036
1037                 switch (mc) {
1038                 case CC_MC_BYPASS:      return (clock);
1039                 case CC_MC_M1:          return (clock / m1);
1040                 case CC_MC_M1M2:        return (clock / (m1 * m2));
1041                 case CC_MC_M1M2M3:      return (clock / (m1 * m2 * m3));
1042                 case CC_MC_M1M3:        return (clock / (m1 * m3));
1043                 default:                return (0);
1044                 }
1045         } else {
1046                 ASSERT(pll_type == PLL_TYPE2);
1047
1048                 m1 += CC_T2_BIAS;
1049                 m2 += CC_T2M2_BIAS;
1050                 m3 += CC_T2_BIAS;
1051                 ASSERT((m1 >= 2) && (m1 <= 7));
1052                 ASSERT((m2 >= 3) && (m2 <= 10));
1053                 ASSERT((m3 >= 2) && (m3 <= 7));
1054
1055                 if ((mc & CC_T2MC_M1BYP) == 0)
1056                         clock /= m1;
1057                 if ((mc & CC_T2MC_M2BYP) == 0)
1058                         clock /= m2;
1059                 if ((mc & CC_T2MC_M3BYP) == 0)
1060                         clock /= m3;
1061
1062                 return (clock);
1063         }
1064 }
1065
1066
1067 /* set chip watchdog reset timer to fire in 'ticks' */
1068 void
1069 si_watchdog(si_t *sih, uint ticks)
1070 {
1071         uint nb, maxt;
1072
1073         if (PMUCTL_ENAB(sih)) {
1074
1075                 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1076                     (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1077                         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1078                         si_setcore(sih, USB20D_CORE_ID, 0);
1079                         si_core_disable(sih, 1);
1080                         si_setcore(sih, CC_CORE_ID, 0);
1081                 }
1082
1083                 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1084                 /* The mips compiler uses the sllv instruction,
1085                  * so we specially handle the 32-bit case.
1086                  */
1087                 if (nb == 32)
1088                         maxt = 0xffffffff;
1089                 else
1090                         maxt = ((1 << nb) - 1);
1091
1092                 if (ticks == 1)
1093                         ticks = 2;
1094                 else if (ticks > maxt)
1095                         ticks = maxt;
1096
1097                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1098         } else {
1099                 maxt = (1 << 28) - 1;
1100                 if (ticks > maxt)
1101                         ticks = maxt;
1102
1103                 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1104         }
1105 }
1106
1107 /* trigger watchdog reset after ms milliseconds */
1108 void
1109 si_watchdog_ms(si_t *sih, uint32 ms)
1110 {
1111         si_watchdog(sih, wd_msticks * ms);
1112 }
1113
1114
1115
1116
1117 /* return the slow clock source - LPO, XTAL, or PCI */
1118 static uint
1119 si_slowclk_src(si_info_t *sii)
1120 {
1121         chipcregs_t *cc;
1122
1123         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1124
1125         if (sii->pub.ccrev < 6) {
1126                 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1127                     (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1128                      PCI_CFG_GPIO_SCS))
1129                         return (SCC_SS_PCI);
1130                 else
1131                         return (SCC_SS_XTAL);
1132         } else if (sii->pub.ccrev < 10) {
1133                 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1134                 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1135         } else  /* Insta-clock */
1136                 return (SCC_SS_XTAL);
1137 }
1138
1139 /* return the ILP (slowclock) min or max frequency */
1140 static uint
1141 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1142 {
1143         uint32 slowclk;
1144         uint div;
1145
1146         ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1147
1148         /* shouldn't be here unless we've established the chip has dynamic clk control */
1149         ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1150
1151         slowclk = si_slowclk_src(sii);
1152         if (sii->pub.ccrev < 6) {
1153                 if (slowclk == SCC_SS_PCI)
1154                         return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1155                 else
1156                         return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1157         } else if (sii->pub.ccrev < 10) {
1158                 div = 4 *
1159                         (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1160                 if (slowclk == SCC_SS_LPO)
1161                         return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1162                 else if (slowclk == SCC_SS_XTAL)
1163                         return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1164                 else if (slowclk == SCC_SS_PCI)
1165                         return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1166                 else
1167                         ASSERT(0);
1168         } else {
1169                 /* Chipc rev 10 is InstaClock */
1170                 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1171                 div = 4 * (div + 1);
1172                 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1173         }
1174         return (0);
1175 }
1176
1177 static void
1178 si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1179 {
1180         chipcregs_t *cc = (chipcregs_t *)chipcregs;
1181         uint slowmaxfreq, pll_delay, slowclk;
1182         uint pll_on_delay, fref_sel_delay;
1183
1184         pll_delay = PLL_DELAY;
1185
1186         /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1187          * since the xtal will also be powered down by dynamic clk control logic.
1188          */
1189
1190         slowclk = si_slowclk_src(sii);
1191         if (slowclk != SCC_SS_XTAL)
1192                 pll_delay += XTAL_ON_DELAY;
1193
1194         /* Starting with 4318 it is ILP that is used for the delays */
1195         slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1196
1197         pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1198         fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1199
1200         W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1201         W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1202 }
1203
1204 /* initialize power control delay registers */
1205 void
1206 si_clkctl_init(si_t *sih)
1207 {
1208         si_info_t *sii;
1209         uint origidx = 0;
1210         chipcregs_t *cc;
1211         bool fast;
1212
1213         if (!CCCTL_ENAB(sih))
1214                 return;
1215
1216         sii = SI_INFO(sih);
1217         fast = SI_FAST(sii);
1218         if (!fast) {
1219                 origidx = sii->curidx;
1220                 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1221                         return;
1222         } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1223                 return;
1224         ASSERT(cc != NULL);
1225
1226         /* set all Instaclk chip ILP to 1 MHz */
1227         if (sih->ccrev >= 10)
1228                 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1229                         (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1230
1231         si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1232
1233         if (!fast)
1234                 si_setcoreidx(sih, origidx);
1235 }
1236
1237
1238 /* change logical "focus" to the gpio core for optimized access */
1239 void *
1240 si_gpiosetcore(si_t *sih)
1241 {
1242         return (si_setcoreidx(sih, SI_CC_IDX));
1243 }
1244
1245 /* mask&set gpiocontrol bits */
1246 uint32
1247 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1248 {
1249         uint regoff;
1250
1251         regoff = 0;
1252
1253         /* gpios could be shared on router platforms
1254          * ignore reservation if it's high priority (e.g., test apps)
1255          */
1256         if ((priority != GPIO_HI_PRIORITY) &&
1257             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1258                 mask = priority ? (si_gpioreservation & mask) :
1259                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1260                 val &= mask;
1261         }
1262
1263         regoff = OFFSETOF(chipcregs_t, gpiocontrol);
1264         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1265 }
1266
1267 /* mask&set gpio output enable bits */
1268 uint32
1269 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1270 {
1271         uint regoff;
1272
1273         regoff = 0;
1274
1275         /* gpios could be shared on router platforms
1276          * ignore reservation if it's high priority (e.g., test apps)
1277          */
1278         if ((priority != GPIO_HI_PRIORITY) &&
1279             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1280                 mask = priority ? (si_gpioreservation & mask) :
1281                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1282                 val &= mask;
1283         }
1284
1285         regoff = OFFSETOF(chipcregs_t, gpioouten);
1286         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1287 }
1288
1289 /* mask&set gpio output bits */
1290 uint32
1291 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1292 {
1293         uint regoff;
1294
1295         regoff = 0;
1296
1297         /* gpios could be shared on router platforms
1298          * ignore reservation if it's high priority (e.g., test apps)
1299          */
1300         if ((priority != GPIO_HI_PRIORITY) &&
1301             (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1302                 mask = priority ? (si_gpioreservation & mask) :
1303                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1304                 val &= mask;
1305         }
1306
1307         regoff = OFFSETOF(chipcregs_t, gpioout);
1308         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1309 }
1310
1311 /* reserve one gpio */
1312 uint32
1313 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1314 {
1315         si_info_t *sii;
1316
1317         sii = SI_INFO(sih);
1318
1319         /* only cores on SI_BUS share GPIO's and only applcation users need to
1320          * reserve/release GPIO
1321          */
1322         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1323                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1324                 return 0xffffffff;
1325         }
1326         /* make sure only one bit is set */
1327         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1328                 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1329                 return 0xffffffff;
1330         }
1331
1332         /* already reserved */
1333         if (si_gpioreservation & gpio_bitmask)
1334                 return 0xffffffff;
1335         /* set reservation */
1336         si_gpioreservation |= gpio_bitmask;
1337
1338         return si_gpioreservation;
1339 }
1340
1341 /* release one gpio */
1342 /*
1343  * releasing the gpio doesn't change the current value on the GPIO last write value
1344  * persists till some one overwrites it
1345  */
1346
1347 uint32
1348 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1349 {
1350         si_info_t *sii;
1351
1352         sii = SI_INFO(sih);
1353
1354         /* only cores on SI_BUS share GPIO's and only applcation users need to
1355          * reserve/release GPIO
1356          */
1357         if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1358                 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1359                 return 0xffffffff;
1360         }
1361         /* make sure only one bit is set */
1362         if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1363                 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1364                 return 0xffffffff;
1365         }
1366
1367         /* already released */
1368         if (!(si_gpioreservation & gpio_bitmask))
1369                 return 0xffffffff;
1370
1371         /* clear reservation */
1372         si_gpioreservation &= ~gpio_bitmask;
1373
1374         return si_gpioreservation;
1375 }
1376
1377 /* return the current gpioin register value */
1378 uint32
1379 si_gpioin(si_t *sih)
1380 {
1381         si_info_t *sii;
1382         uint regoff;
1383
1384         sii = SI_INFO(sih);
1385         regoff = 0;
1386
1387         regoff = OFFSETOF(chipcregs_t, gpioin);
1388         return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
1389 }
1390
1391 /* mask&set gpio interrupt polarity bits */
1392 uint32
1393 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1394 {
1395         si_info_t *sii;
1396         uint regoff;
1397
1398         sii = SI_INFO(sih);
1399         regoff = 0;
1400
1401         /* gpios could be shared on router platforms */
1402         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1403                 mask = priority ? (si_gpioreservation & mask) :
1404                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1405                 val &= mask;
1406         }
1407
1408         regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
1409         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1410 }
1411
1412 /* mask&set gpio interrupt mask bits */
1413 uint32
1414 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1415 {
1416         si_info_t *sii;
1417         uint regoff;
1418
1419         sii = SI_INFO(sih);
1420         regoff = 0;
1421
1422         /* gpios could be shared on router platforms */
1423         if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1424                 mask = priority ? (si_gpioreservation & mask) :
1425                         ((si_gpioreservation | mask) & ~(si_gpioreservation));
1426                 val &= mask;
1427         }
1428
1429         regoff = OFFSETOF(chipcregs_t, gpiointmask);
1430         return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1431 }
1432
1433 /* assign the gpio to an led */
1434 uint32
1435 si_gpioled(si_t *sih, uint32 mask, uint32 val)
1436 {
1437         si_info_t *sii;
1438
1439         sii = SI_INFO(sih);
1440         if (sih->ccrev < 16)
1441                 return 0xffffffff;
1442
1443         /* gpio led powersave reg */
1444         return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
1445 }
1446
1447 /* mask&set gpio timer val */
1448 uint32
1449 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
1450 {
1451         si_info_t *sii;
1452
1453         sii = SI_INFO(sih);
1454
1455         if (sih->ccrev < 16)
1456                 return 0xffffffff;
1457
1458         return (si_corereg(sih, SI_CC_IDX,
1459                 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
1460 }
1461
1462 uint32
1463 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
1464 {
1465         si_info_t *sii;
1466         uint offs;
1467
1468         sii = SI_INFO(sih);
1469         if (sih->ccrev < 20)
1470                 return 0xffffffff;
1471
1472         offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
1473         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1474 }
1475
1476 uint32
1477 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
1478 {
1479         si_info_t *sii;
1480         uint offs;
1481
1482         sii = SI_INFO(sih);
1483         if (sih->ccrev < 11)
1484                 return 0xffffffff;
1485
1486         if (regtype == GPIO_REGEVT)
1487                 offs = OFFSETOF(chipcregs_t, gpioevent);
1488         else if (regtype == GPIO_REGEVT_INTMSK)
1489                 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
1490         else if (regtype == GPIO_REGEVT_INTPOL)
1491                 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
1492         else
1493                 return 0xffffffff;
1494
1495         return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1496 }
1497
1498 void *
1499 si_gpio_handler_register(si_t *sih, uint32 event,
1500         bool level, gpio_handler_t cb, void *arg)
1501 {
1502         si_info_t *sii;
1503         gpioh_item_t *gi;
1504
1505         ASSERT(event);
1506         ASSERT(cb != NULL);
1507
1508         sii = SI_INFO(sih);
1509         if (sih->ccrev < 11)
1510                 return NULL;
1511
1512         if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
1513                 return NULL;
1514
1515         bzero(gi, sizeof(gpioh_item_t));
1516         gi->event = event;
1517         gi->handler = cb;
1518         gi->arg = arg;
1519         gi->level = level;
1520
1521         gi->next = sii->gpioh_head;
1522         sii->gpioh_head = gi;
1523
1524         return (void *)(gi);
1525 }
1526
1527 void
1528 si_gpio_handler_unregister(si_t *sih, void *gpioh)
1529 {
1530         si_info_t *sii;
1531         gpioh_item_t *p, *n;
1532
1533         sii = SI_INFO(sih);
1534         if (sih->ccrev < 11)
1535                 return;
1536
1537         ASSERT(sii->gpioh_head != NULL);
1538         if ((void*)sii->gpioh_head == gpioh) {
1539                 sii->gpioh_head = sii->gpioh_head->next;
1540                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1541                 return;
1542         } else {
1543                 p = sii->gpioh_head;
1544                 n = p->next;
1545                 while (n) {
1546                         if ((void*)n == gpioh) {
1547                                 p->next = n->next;
1548                                 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1549                                 return;
1550                         }
1551                         p = n;
1552                         n = n->next;
1553                 }
1554         }
1555
1556         ASSERT(0); /* Not found in list */
1557 }
1558
1559 void
1560 si_gpio_handler_process(si_t *sih)
1561 {
1562         si_info_t *sii;
1563         gpioh_item_t *h;
1564         uint32 status;
1565         uint32 level = si_gpioin(sih);
1566         uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
1567
1568         sii = SI_INFO(sih);
1569         for (h = sii->gpioh_head; h != NULL; h = h->next) {
1570                 if (h->handler) {
1571                         status = (h->level ? level : edge);
1572
1573                         if (status & h->event)
1574                                 h->handler(status, h->arg);
1575                 }
1576         }
1577
1578         si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
1579 }
1580
1581 uint32
1582 si_gpio_int_enable(si_t *sih, bool enable)
1583 {
1584         si_info_t *sii;
1585         uint offs;
1586
1587         sii = SI_INFO(sih);
1588         if (sih->ccrev < 11)
1589                 return 0xffffffff;
1590
1591         offs = OFFSETOF(chipcregs_t, intmask);
1592         return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
1593 }
1594
1595
1596 /* Return the size of the specified SOCRAM bank */
1597 static uint
1598 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type)
1599 {
1600         uint banksize, bankinfo;
1601         uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1602
1603         ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1604
1605         W_REG(sii->osh, &regs->bankidx, bankidx);
1606         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1607         banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1608         return banksize;
1609 }
1610
1611 void
1612 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
1613 {
1614         si_info_t *sii;
1615         uint origidx;
1616         uint intr_val = 0;
1617         sbsocramregs_t *regs;
1618         bool wasup;
1619         uint corerev;
1620
1621         sii = SI_INFO(sih);
1622
1623         /* Block ints and save current core */
1624         INTR_OFF(sii, intr_val);
1625         origidx = si_coreidx(sih);
1626
1627         if (!set)
1628                 *enable = *protect = 0;
1629
1630         /* Switch to SOCRAM core */
1631         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1632                 goto done;
1633
1634         /* Get info for determining size */
1635         if (!(wasup = si_iscoreup(sih)))
1636                 si_core_reset(sih, 0, 0);
1637
1638         corerev = si_corerev(sih);
1639         if (corerev >= 10) {
1640                 uint32 extcinfo;
1641                 uint8 nb;
1642                 uint8 i;
1643                 uint32 bankidx, bankinfo;
1644
1645                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1646                 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1647                 for (i = 0; i < nb; i++) {
1648                         bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1649                         W_REG(sii->osh, &regs->bankidx, bankidx);
1650                         bankinfo = R_REG(sii->osh, &regs->bankinfo);
1651                         if (set) {
1652                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
1653                                 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
1654                                 if (*enable) {
1655                                         bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
1656                                         if (*protect)
1657                                                 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
1658                                 }
1659                                 W_REG(sii->osh, &regs->bankinfo, bankinfo);
1660                         }
1661                         else if (i == 0) {
1662                                 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
1663                                         *enable = 1;
1664                                         if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
1665                                                 *protect = 1;
1666                                 }
1667                         }
1668                 }
1669         }
1670
1671         /* Return to previous state and core */
1672         if (!wasup)
1673                 si_core_disable(sih, 0);
1674         si_setcoreidx(sih, origidx);
1675
1676 done:
1677         INTR_RESTORE(sii, intr_val);
1678 }
1679
1680 bool
1681 si_socdevram_pkg(si_t *sih)
1682 {
1683         if (si_socdevram_size(sih) > 0)
1684                 return TRUE;
1685         else
1686                 return FALSE;
1687 }
1688
1689 uint32
1690 si_socdevram_size(si_t *sih)
1691 {
1692         si_info_t *sii;
1693         uint origidx;
1694         uint intr_val = 0;
1695         uint32 memsize = 0;
1696         sbsocramregs_t *regs;
1697         bool wasup;
1698         uint corerev;
1699
1700         sii = SI_INFO(sih);
1701
1702         /* Block ints and save current core */
1703         INTR_OFF(sii, intr_val);
1704         origidx = si_coreidx(sih);
1705
1706         /* Switch to SOCRAM core */
1707         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1708                 goto done;
1709
1710         /* Get info for determining size */
1711         if (!(wasup = si_iscoreup(sih)))
1712                 si_core_reset(sih, 0, 0);
1713
1714         corerev = si_corerev(sih);
1715         if (corerev >= 10) {
1716                 uint32 extcinfo;
1717                 uint8 nb;
1718                 uint8 i;
1719
1720                 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1721                 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1722                 for (i = 0; i < nb; i++)
1723                         memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1724         }
1725
1726         /* Return to previous state and core */
1727         if (!wasup)
1728                 si_core_disable(sih, 0);
1729         si_setcoreidx(sih, origidx);
1730
1731 done:
1732         INTR_RESTORE(sii, intr_val);
1733
1734         return memsize;
1735 }
1736
1737 /* Return the RAM size of the SOCRAM core */
1738 uint32
1739 si_socram_size(si_t *sih)
1740 {
1741         si_info_t *sii;
1742         uint origidx;
1743         uint intr_val = 0;
1744
1745         sbsocramregs_t *regs;
1746         bool wasup;
1747         uint corerev;
1748         uint32 coreinfo;
1749         uint memsize = 0;
1750
1751         sii = SI_INFO(sih);
1752
1753         /* Block ints and save current core */
1754         INTR_OFF(sii, intr_val);
1755         origidx = si_coreidx(sih);
1756
1757         /* Switch to SOCRAM core */
1758         if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1759                 goto done;
1760
1761         /* Get info for determining size */
1762         if (!(wasup = si_iscoreup(sih)))
1763                 si_core_reset(sih, 0, 0);
1764         corerev = si_corerev(sih);
1765         coreinfo = R_REG(sii->osh, &regs->coreinfo);
1766
1767         /* Calculate size from coreinfo based on rev */
1768         if (corerev == 0)
1769                 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1770         else if (corerev < 3) {
1771                 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1772                 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1773         } else if ((corerev <= 7) || (corerev == 12)) {
1774                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1775                 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1776                 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1777                 if (lss != 0)
1778                         nb --;
1779                 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1780                 if (lss != 0)
1781                         memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1782         } else {
1783                 uint8 i;
1784                 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1785                 for (i = 0; i < nb; i++)
1786                         memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1787         }
1788
1789         /* Return to previous state and core */
1790         if (!wasup)
1791                 si_core_disable(sih, 0);
1792         si_setcoreidx(sih, origidx);
1793
1794 done:
1795         INTR_RESTORE(sii, intr_val);
1796
1797         return memsize;
1798 }
1799
1800
1801 void
1802 si_btcgpiowar(si_t *sih)
1803 {
1804         si_info_t *sii;
1805         uint origidx;
1806         uint intr_val = 0;
1807         chipcregs_t *cc;
1808
1809         sii = SI_INFO(sih);
1810
1811         /* Make sure that there is ChipCommon core present &&
1812          * UART_TX is strapped to 1
1813          */
1814         if (!(sih->cccaps & CC_CAP_UARTGPIO))
1815                 return;
1816
1817         /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
1818         INTR_OFF(sii, intr_val);
1819
1820         origidx = si_coreidx(sih);
1821
1822         cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1823         ASSERT(cc != NULL);
1824
1825         W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
1826
1827         /* restore the original index */
1828         si_setcoreidx(sih, origidx);
1829
1830         INTR_RESTORE(sii, intr_val);
1831 }
1832
1833 uint
1834 si_pll_reset(si_t *sih)
1835 {
1836         uint err = 0;
1837
1838         return (err);
1839 }
1840
1841 /* check if the device is removed */
1842 bool
1843 si_deviceremoved(si_t *sih)
1844 {
1845         uint32 w;
1846         si_info_t *sii;
1847
1848         sii = SI_INFO(sih);
1849
1850         switch (BUSTYPE(sih->bustype)) {
1851         case PCI_BUS:
1852                 ASSERT(sii->osh != NULL);
1853                 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
1854                 if ((w & 0xFFFF) != VENDOR_BROADCOM)
1855                         return TRUE;
1856                 break;
1857         }
1858         return FALSE;
1859 }
1860
1861 bool
1862 si_is_sprom_available(si_t *sih)
1863 {
1864         if (sih->ccrev >= 31) {
1865                 si_info_t *sii;
1866                 uint origidx;
1867                 chipcregs_t *cc;
1868                 uint32 sromctrl;
1869
1870                 if ((sih->cccaps & CC_CAP_SROM) == 0)
1871                         return FALSE;
1872
1873                 sii = SI_INFO(sih);
1874                 origidx = sii->curidx;
1875                 cc = si_setcoreidx(sih, SI_CC_IDX);
1876                 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
1877                 si_setcoreidx(sih, origidx);
1878                 return (sromctrl & SRC_PRESENT);
1879         }
1880
1881         switch (CHIPID(sih->chip)) {
1882         case BCM4312_CHIP_ID:
1883                 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
1884         case BCM4325_CHIP_ID:
1885                 return (sih->chipst & CST4325_SPROM_SEL) != 0;
1886         case BCM4322_CHIP_ID:
1887         case BCM43221_CHIP_ID:
1888         case BCM43231_CHIP_ID:
1889         case BCM43222_CHIP_ID:
1890         case BCM43111_CHIP_ID:
1891         case BCM43112_CHIP_ID:
1892         case BCM4342_CHIP_ID:
1893         {
1894                 uint32 spromotp;
1895                 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
1896                         CST4322_SPROM_OTP_SEL_SHIFT;
1897                 return (spromotp & CST4322_SPROM_PRESENT) != 0;
1898         }
1899         case BCM4329_CHIP_ID:
1900                 return (sih->chipst & CST4329_SPROM_SEL) != 0;
1901         case BCM4315_CHIP_ID:
1902                 return (sih->chipst & CST4315_SPROM_SEL) != 0;
1903         case BCM4319_CHIP_ID:
1904                 return (sih->chipst & CST4319_SPROM_SEL) != 0;
1905         case BCM4336_CHIP_ID:
1906         case BCM43362_CHIP_ID:
1907                 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
1908         case BCM4330_CHIP_ID:
1909                 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
1910         case BCM4313_CHIP_ID:
1911                 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
1912         case BCM43239_CHIP_ID:
1913                 return ((sih->chipst & CST43239_SPROM_MASK) &&
1914                         !(sih->chipst & CST43239_SFLASH_MASK));
1915         default:
1916                 return TRUE;
1917         }
1918 }