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