K2.6 patches and update.
[tomato.git] / release / src-rt / shared / siutils.c
blob297fe87c185a1a635426163e41835585eb4ebfa7
1 /*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <bcmdevs.h>
28 #include <hndsoc.h>
29 #include <sbchipc.h>
30 #include <pci_core.h>
31 #include <pcie_core.h>
32 #include <nicpci.h>
33 #include <bcmnvram.h>
34 #include <bcmsrom.h>
35 #include <hndtcam.h>
36 #include <pcicfg.h>
37 #include <sbpcmcia.h>
38 #include <sbsocram.h>
39 #include <bcmotp.h>
40 #include <hndpmu.h>
41 #ifdef BCMSPI
42 #include <spid.h>
43 #endif /* BCMSPI */
45 #include "siutils_priv.h"
47 /* local prototypes */
48 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
49 uint bustype, void *sdh, char **vars, uint *varsz);
50 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
51 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
52 uint *origidx, void *regs);
53 static void si_nvram_process(si_info_t *sii, char *pvars);
54 #if !defined(_CFE_) || defined(CFG_WL)
55 static void si_sromvars_fixup_4331(si_t *sih, char *pvars);
56 #endif /* !_CFE_ || CFG_WL */
58 /* dev path concatenation util */
59 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
60 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
61 static bool si_ispcie(si_info_t *sii);
62 static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype);
65 /* global variable to indicate reservation/release of gpio's */
66 static uint32 si_gpioreservation = 0;
68 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
71 * Allocate a si handle.
72 * devid - pci device id (used to determine chip#)
73 * osh - opaque OS handle
74 * regs - virtual address of initial core registers
75 * bustype - pci/pcmcia/sb/sdio/etc
76 * vars - pointer to a pointer area for "environment" variables
77 * varsz - pointer to int to return the size of the vars
79 si_t *
80 BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs,
81 uint bustype, void *sdh, char **vars, uint *varsz)
83 si_info_t *sii;
85 /* alloc si_info_t */
86 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
87 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
88 return (NULL);
91 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
92 MFREE(osh, sii, sizeof(si_info_t));
93 return (NULL);
95 sii->vars = vars ? *vars : NULL;
96 sii->varsz = varsz ? *varsz : 0;
98 return (si_t *)sii;
101 /* global kernel resource */
102 static si_info_t ksii;
104 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
106 /* generic kernel variant of si_attach() */
107 si_t *
108 BCMATTACHFN(si_kattach)(osl_t *osh)
110 static bool ksii_attached = FALSE;
112 if (!ksii_attached) {
113 void *regs;
114 #ifndef SI_ENUM_BASE_VARIABLE
115 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
116 #endif
118 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
119 SI_BUS, NULL,
120 osh != SI_OSH ? &ksii.vars : NULL,
121 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
122 SI_ERROR(("si_kattach: si_doattach failed\n"));
123 REG_UNMAP(regs);
124 return NULL;
126 REG_UNMAP(regs);
128 /* save ticks normalized to ms for si_watchdog_ms() */
129 if (PMUCTL_ENAB(&ksii.pub)) {
130 if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) {
131 /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
132 wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000;
134 else
135 /* based on 32KHz ILP clock */
136 wd_msticks = 32;
137 } else {
138 if (ksii.pub.ccrev < 18)
139 wd_msticks = si_clock(&ksii.pub) / 1000;
140 else
141 wd_msticks = si_alp_clock(&ksii.pub) / 1000;
144 ksii_attached = TRUE;
145 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
146 ksii.pub.ccrev, wd_msticks));
149 return &ksii.pub;
152 bool
153 si_ldo_war(si_t *sih, uint devid)
155 si_info_t *sii = SI_INFO(sih);
156 uint32 w;
157 chipcregs_t *cc;
158 void *regs = sii->curmap;
159 uint32 rev_id, ccst;
161 rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32));
162 rev_id &= 0xff;
163 if (!(((CHIPID(devid) == BCM4322_CHIP_ID) ||
164 (CHIPID(devid) == BCM4342_CHIP_ID) ||
165 (CHIPID(devid) == BCM4322_D11N_ID) ||
166 (CHIPID(devid) == BCM4322_D11N2G_ID) ||
167 (CHIPID(devid) == BCM4322_D11N5G_ID)) &&
168 (rev_id == 0)))
169 return TRUE;
171 SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id));
173 /* switch to chipcommon */
174 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
175 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE);
176 cc = (chipcregs_t *)regs;
178 /* clear bit 7 to fix LDO
179 * write to register *blindly* WITHOUT read since read may timeout
180 * because the default clock is 32k ILP
182 W_REG(sii->osh, &cc->regcontrol_addr, 0);
183 /* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
184 W_REG(sii->osh, &cc->regcontrol_data, 0x3001);
186 OSL_DELAY(5000);
188 /* request ALP_AVAIL through PMU to move sb out of ILP */
189 W_REG(sii->osh, &cc->min_res_mask, 0x0d);
191 SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL)
192 == 0, PMU_MAX_TRANSITION_DLY);
194 if ((ccst & CCS_ALPAVAIL) == 0) {
195 SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst));
196 return FALSE;
198 SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
200 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w);
202 return TRUE;
205 static bool
206 BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh)
208 /* need to set memseg flag for CF card first before any sb registers access */
209 if (BUSTYPE(bustype) == PCMCIA_BUS)
210 sii->memseg = TRUE;
212 if (BUSTYPE(bustype) == PCI_BUS) {
213 if (!si_ldo_war((si_t *)sii, devid))
214 return FALSE;
217 /* kludge to enable the clock on the 4306 which lacks a slowclock */
218 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
219 si_clkctl_xtal(&sii->pub, XTAL|PLL, ON);
222 return TRUE;
225 static bool
226 BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
227 uint *origidx, void *regs)
229 bool pci, pcie;
230 uint i;
231 uint pciidx, pcieidx, pcirev, pcierev;
233 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
234 ASSERT((uintptr)cc);
236 /* get chipcommon rev */
237 sii->pub.ccrev = (int)si_corerev(&sii->pub);
239 /* get chipcommon chipstatus */
240 if (sii->pub.ccrev >= 11)
241 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
243 /* get chipcommon capabilites */
244 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
245 /* get chipcommon extended capabilities */
247 if (sii->pub.ccrev >= 35)
248 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
250 /* get pmu rev and caps */
251 if (sii->pub.cccaps & CC_CAP_PMU) {
252 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
253 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
256 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
257 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
258 sii->pub.pmucaps));
260 /* figure out bus/orignal core idx */
261 sii->pub.buscoretype = NODEV_CORE_ID;
262 sii->pub.buscorerev = NOREV;
263 sii->pub.buscoreidx = BADIDX;
265 pci = pcie = FALSE;
266 pcirev = pcierev = NOREV;
267 pciidx = pcieidx = BADIDX;
269 for (i = 0; i < sii->numcores; i++) {
270 uint cid, crev;
272 si_setcoreidx(&sii->pub, i);
273 cid = si_coreid(&sii->pub);
274 crev = si_corerev(&sii->pub);
276 /* Display cores found */
277 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
278 i, cid, crev, sii->coresba[i], sii->regs[i]));
280 if (BUSTYPE(bustype) == PCI_BUS) {
281 if (cid == PCI_CORE_ID) {
282 pciidx = i;
283 pcirev = crev;
284 pci = TRUE;
285 } else if (cid == PCIE_CORE_ID) {
286 pcieidx = i;
287 pcierev = crev;
288 pcie = TRUE;
290 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
291 (cid == PCMCIA_CORE_ID)) {
292 sii->pub.buscorerev = crev;
293 sii->pub.buscoretype = cid;
294 sii->pub.buscoreidx = i;
297 /* find the core idx before entering this func. */
298 if ((savewin && (savewin == sii->coresba[i])) ||
299 (regs == sii->regs[i]))
300 *origidx = i;
303 if (pci && pcie) {
304 if (si_ispcie(sii))
305 pci = FALSE;
306 else
307 pcie = FALSE;
309 if (pci) {
310 sii->pub.buscoretype = PCI_CORE_ID;
311 sii->pub.buscorerev = pcirev;
312 sii->pub.buscoreidx = pciidx;
313 } else if (pcie) {
314 sii->pub.buscoretype = PCIE_CORE_ID;
315 sii->pub.buscorerev = pcierev;
316 sii->pub.buscoreidx = pcieidx;
319 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
320 sii->pub.buscorerev));
322 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
323 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
324 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
326 /* fixup necessary chip/core configurations */
327 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
328 if (SI_FAST(sii)) {
329 if (!sii->pch &&
330 ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh,
331 (void *)PCIEREGS(sii))) == NULL))
332 return FALSE;
334 if (si_pci_fixcfg(&sii->pub)) {
335 SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
336 return FALSE;
341 /* return to the original core */
342 si_setcoreidx(&sii->pub, *origidx);
344 return TRUE;
347 static void
348 BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars)
350 uint w = 0;
351 if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
352 w = getintvar(pvars, "regwindowsz");
353 sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
356 /* get boardtype and boardrev */
357 switch (BUSTYPE(sii->pub.bustype)) {
358 case PCI_BUS:
359 #if defined(BCMHOSTVARS)
360 sii->pub.boardvendor = VENDOR_BROADCOM;
361 sii->pub.boardtype = getintvar(pvars, "boardtype");
362 #else /* !BCMHOSTVARS */
363 /* do a pci config read to get subsystem id and subvendor id */
364 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
365 /* Let nvram variables override subsystem Vend/ID */
366 if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor"))
367 == 0)
368 sii->pub.boardvendor = w & 0xffff;
369 else
370 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
371 sii->pub.boardvendor, w & 0xffff));
372 if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype"))
373 == 0)
374 sii->pub.boardtype = (w >> 16) & 0xffff;
375 else
376 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
377 sii->pub.boardtype, (w >> 16) & 0xffff));
378 #endif /* BCMHOSTVARS */
379 break;
381 case PCMCIA_BUS:
382 sii->pub.boardvendor = getintvar(pvars, "manfid");
383 sii->pub.boardtype = getintvar(pvars, "prodid");
384 break;
387 case SI_BUS:
388 case JTAG_BUS:
389 sii->pub.boardvendor = VENDOR_BROADCOM;
390 if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
391 if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0)
392 sii->pub.boardtype = 0xffff;
394 if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
395 /* do a pci config read to get subsystem id and subvendor id */
396 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
397 sii->pub.boardvendor = w & 0xffff;
398 sii->pub.boardtype = (w >> 16) & 0xffff;
400 break;
403 if (sii->pub.boardtype == 0) {
404 SI_ERROR(("si_doattach: unknown board type\n"));
405 ASSERT(sii->pub.boardtype);
408 sii->pub.boardrev = getintvar(pvars, "boardrev");
409 sii->pub.boardflags = getintvar(pvars, "boardflags");
412 #if !defined(_CFE_) || defined(CFG_WL)
413 static void
414 BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars)
417 const char *sromvars[] =
418 {"extpagain2g", "extpagain5g"};
419 int sromvars_size = sizeof(sromvars)/sizeof(char *);
420 int ii;
421 uint boardtype = sih->boardtype;
422 uint boardrev = sih->boardrev;
423 bool update = ((boardtype == BCM94331BU_SSID) ||
424 (boardtype == BCM94331S9BU_SSID) ||
425 (boardtype == BCM94331MCI_SSID) ||
426 (boardtype == BCM94331MC_SSID) ||
427 (boardtype == BCM94331PCIEBT4_SSID) ||
428 (boardtype == BCM94331X19 && boardrev == 0x1100) ||
429 (boardtype == BCM94331HM_SSID && boardrev < 0x1152));
431 if (pvars == NULL || !update) {
432 return;
435 for (ii = 0; ii < sromvars_size; ii++) {
436 char* val = getvar(pvars, sromvars[ii]);
438 while (val && *val) {
439 *val = '0';
440 val++;
444 #endif /* !_CFE_ || CFG_WL */
446 #ifdef CONFIG_XIP
447 extern uint8 patch_pair;
448 #endif /* CONFIG_XIP */
450 static si_info_t *
451 BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs,
452 uint bustype, void *sdh, char **vars, uint *varsz)
454 struct si_pub *sih = &sii->pub;
455 uint32 w, savewin;
456 chipcregs_t *cc;
457 char *pvars = NULL;
458 uint origidx;
460 ASSERT(GOODREGS(regs));
462 bzero((uchar*)sii, sizeof(si_info_t));
464 savewin = 0;
466 sih->buscoreidx = BADIDX;
468 sii->curmap = regs;
469 sii->sdh = sdh;
470 sii->osh = osh;
472 #ifdef SI_ENUM_BASE_VARIABLE
473 si_enum_base_init(sih, bustype);
474 #endif /* SI_ENUM_BASE_VARIABLE */
476 /* check to see if we are a si core mimic'ing a pci core */
477 if ((bustype == PCI_BUS) &&
478 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
479 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
480 "devid:0x%x\n", __FUNCTION__, devid));
481 bustype = SI_BUS;
484 /* find Chipcommon address */
485 if (bustype == PCI_BUS) {
486 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
487 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
488 savewin = SI_ENUM_BASE;
489 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
490 cc = (chipcregs_t *)regs;
491 } else {
492 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
495 sih->bustype = bustype;
496 if (bustype != BUSTYPE(bustype)) {
497 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
498 bustype, BUSTYPE(bustype)));
499 return NULL;
502 /* bus/core/clk setup for register access */
503 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
504 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
505 return NULL;
508 /* ChipID recognition.
509 * We assume we can read chipid at offset 0 from the regs arg.
510 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
511 * some way of recognizing them needs to be added here.
513 w = R_REG(osh, &cc->chipid);
514 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
515 /* Might as wll fill in chip id rev & pkg */
516 sih->chip = w & CID_ID_MASK;
517 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
518 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
520 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
521 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
522 sih->chippkg = BCM4329_182PIN_PKG_ID;
524 sih->issim = IS_SIM(sih->chippkg);
526 /* scan for cores */
527 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
528 SI_MSG(("Found chip type SB (0x%08x)\n", w));
529 sb_scan(&sii->pub, regs, devid);
530 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
531 SI_MSG(("Found chip type AI (0x%08x)\n", w));
532 /* pass chipc address instead of original core base */
533 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
534 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
535 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
536 /* pass chipc address instead of original core base */
537 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
538 } else {
539 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
540 return NULL;
542 /* no cores found, bail out */
543 if (sii->numcores == 0) {
544 SI_ERROR(("si_doattach: could not find any cores\n"));
545 return NULL;
547 /* bus/core/clk setup */
548 origidx = SI_CC_IDX;
549 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
550 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
551 goto exit;
554 #if !defined(_CFE_) || defined(CFG_WL)
555 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
556 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
557 CST4322_SPROM_PRESENT))) {
558 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
559 return NULL;
562 /* assume current core is CC */
563 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
564 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
565 CHIPID(sih->chip) == BCM43234_CHIP_ID ||
566 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
567 (CHIPREV(sii->pub.chiprev) <= 2))) {
569 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
570 uint clkdiv;
571 clkdiv = R_REG(osh, &cc->clkdiv);
572 /* otp_clk_div is even number, 120/14 < 9mhz */
573 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
574 W_REG(osh, &cc->clkdiv, clkdiv);
575 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
577 OSL_DELAY(10);
580 if (bustype == PCI_BUS) {
581 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
582 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
583 /* set default mux pin to SROM */
584 si_chipcontrl_epa4331(sih, FALSE);
585 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100);
586 OSL_DELAY(20000); /* Srom read takes ~12mS */
588 #ifdef BCMQT
589 /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
590 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
591 * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words.
594 uint otpclkdiv = 0;
596 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
597 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
598 otpclkdiv = 2;
599 } else if ((CHIPID(sih->chip) == BCM43227_CHIP_ID) ||
600 (CHIPID(sih->chip) == BCM43131_CHIP_ID) ||
601 (CHIPID(sih->chip) == BCM43228_CHIP_ID)) {
602 otpclkdiv = 4;
605 if (otpclkdiv != 0) {
606 uint clkdiv, savecore;
607 savecore = si_coreidx(sih);
608 si_setcore(sih, CC_CORE_ID, 0);
610 clkdiv = R_REG(osh, &cc->clkdiv);
611 clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT);
612 W_REG(osh, &cc->clkdiv, clkdiv);
614 SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv));
615 si_setcoreidx(sih, savecore);
618 #endif /* BCMQT */
620 #endif /* !_CFE_ || CFG_WL */
621 #ifdef SI_SPROM_PROBE
622 si_sprom_init(sih);
623 #endif /* SI_SPROM_PROBE */
625 #if !defined(BCMHIGHSDIO)
626 /* Init nvram from flash if it exists */
627 nvram_init((void *)&(sii->pub));
629 /* Init nvram from sprom/otp if they exist */
630 if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
631 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
632 goto exit;
634 pvars = vars ? *vars : NULL;
635 si_nvram_process(sii, pvars);
637 #if !defined(_CFE_) || defined(CFG_WL)
638 if (bustype == PCI_BUS) {
639 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
640 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
641 si_sromvars_fixup_4331(sih, pvars);
644 #endif /* _!CFE_ || CFG_WL */
646 /* === NVRAM, clock is ready === */
647 #else
648 pvars = NULL;
649 #endif
652 #ifdef CONFIG_XIP
653 /* patch the ROM if there are any patch pairs from OTP/SPROM */
654 if (patch_pair) {
656 hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars);
658 si_setcoreidx(sih, origidx);
660 #endif /* CONFIG_XIP */
662 if (sii->pub.ccrev >= 20) {
663 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
664 W_REG(osh, &cc->gpiopullup, 0);
665 W_REG(osh, &cc->gpiopulldown, 0);
666 si_setcoreidx(sih, origidx);
669 /* PMU specific initializations */
670 if (PMUCTL_ENAB(sih)) {
671 uint32 xtalfreq;
672 si_pmu_init(sih, sii->osh);
673 si_pmu_chip_init(sih, sii->osh);
674 xtalfreq = getintvar(pvars, "xtalfreq");
675 /* If xtalfreq var not available, try to measure it */
676 if (xtalfreq == 0)
677 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
678 si_pmu_pll_init(sih, sii->osh, xtalfreq);
679 si_pmu_res_init(sih, sii->osh);
680 si_pmu_swreg_init(sih, sii->osh);
683 /* setup the GPIO based LED powersave register */
684 if (sii->pub.ccrev >= 16) {
685 if ((w = getintvar(pvars, "leddc")) == 0)
686 w = DEFAULT_GPIOTIMERVAL;
687 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
690 if (PCI_FORCEHT(sii)) {
691 SI_MSG(("si_doattach: force HT\n"));
692 sih->pci_pr32414 = TRUE;
693 si_clkctl_init(sih);
694 _si_clkctl_cc(sii, CLK_FAST);
697 #if !defined(_CFE_) || defined(CFG_WL)
698 if (PCIE(sii)) {
699 ASSERT(sii->pch != NULL);
701 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
703 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
704 (CHIPID(sih->chip) == BCM4312_CHIP_ID)) {
705 SI_MSG(("si_doattach: clear initiator timeout\n"));
706 sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0));
710 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
711 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
712 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
713 if (CHIPREV(sih->chiprev) == 0) {
714 SI_MSG(("Applying 43224A0 WARs\n"));
715 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
716 CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE);
717 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
718 CCTRL_43224A0_12MA_LED_DRIVE);
720 if (CHIPREV(sih->chiprev) >= 1) {
721 SI_MSG(("Applying 43224B0+ WARs\n"));
722 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
723 CCTRL_43224B0_12MA_LED_DRIVE);
727 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
728 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
729 SI_MSG(("Applying 4313 WARs\n"));
730 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, CCTRL_4313_12MA_LED_DRIVE);
732 #endif /* !_CFE_ || CFG_WL */
734 #ifdef BCMDBG
735 /* clear any previous epidiag-induced target abort */
736 si_taclear(sih, FALSE);
737 #endif /* BCMDBG */
739 return (sii);
741 exit:
742 if (BUSTYPE(sih->bustype) == PCI_BUS) {
743 if (sii->pch)
744 pcicore_deinit(sii->pch);
745 sii->pch = NULL;
748 return NULL;
751 /* may be called with core in reset */
752 void
753 BCMATTACHFN(si_detach)(si_t *sih)
755 si_info_t *sii;
756 uint idx;
758 #if defined(STA)
759 struct si_pub *si_local = NULL;
760 bcopy(&sih, &si_local, sizeof(si_t*));
761 #endif
763 sii = SI_INFO(sih);
765 if (sii == NULL)
766 return;
768 if (BUSTYPE(sih->bustype) == SI_BUS)
769 for (idx = 0; idx < SI_MAXCORES; idx++)
770 if (sii->regs[idx]) {
771 REG_UNMAP(sii->regs[idx]);
772 sii->regs[idx] = NULL;
775 #if defined(STA)
776 nvram_exit((void *)si_local); /* free up nvram buffers */
777 #endif
779 if (BUSTYPE(sih->bustype) == PCI_BUS) {
780 if (sii->pch)
781 pcicore_deinit(sii->pch);
782 sii->pch = NULL;
785 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
786 if (sii != &ksii)
787 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
788 MFREE(sii->osh, sii, sizeof(si_info_t));
791 void *
792 si_osh(si_t *sih)
794 si_info_t *sii;
796 sii = SI_INFO(sih);
797 return sii->osh;
800 void
801 si_setosh(si_t *sih, osl_t *osh)
803 si_info_t *sii;
805 sii = SI_INFO(sih);
806 if (sii->osh != NULL) {
807 SI_ERROR(("osh is already set....\n"));
808 ASSERT(!sii->osh);
810 sii->osh = osh;
813 /* register driver interrupt disabling and restoring callback functions */
814 void
815 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
816 void *intrsenabled_fn, void *intr_arg)
818 si_info_t *sii;
820 sii = SI_INFO(sih);
821 sii->intr_arg = intr_arg;
822 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
823 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
824 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
825 /* save current core id. when this function called, the current core
826 * must be the core which provides driver functions(il, et, wl, etc.)
828 sii->dev_coreid = sii->coreid[sii->curidx];
831 void
832 si_deregister_intr_callback(si_t *sih)
834 si_info_t *sii;
836 sii = SI_INFO(sih);
837 sii->intrsoff_fn = NULL;
840 uint
841 si_intflag(si_t *sih)
843 si_info_t *sii = SI_INFO(sih);
845 if (CHIPTYPE(sih->socitype) == SOCI_SB)
846 return sb_intflag(sih);
847 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
848 return R_REG(sii->osh, ((uint32 *)(uintptr)
849 (sii->oob_router + OOB_STATUSA)));
850 else {
851 ASSERT(0);
852 return 0;
856 uint
857 si_flag(si_t *sih)
859 if (CHIPTYPE(sih->socitype) == SOCI_SB)
860 return sb_flag(sih);
861 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
862 return ai_flag(sih);
863 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
864 return ub_flag(sih);
865 else {
866 ASSERT(0);
867 return 0;
871 void
872 si_setint(si_t *sih, int siflag)
874 if (CHIPTYPE(sih->socitype) == SOCI_SB)
875 sb_setint(sih, siflag);
876 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
877 ai_setint(sih, siflag);
878 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
879 ub_setint(sih, siflag);
880 else
881 ASSERT(0);
884 uint
885 si_coreid(si_t *sih)
887 si_info_t *sii;
889 sii = SI_INFO(sih);
890 return sii->coreid[sii->curidx];
893 uint
894 si_coreidx(si_t *sih)
896 si_info_t *sii;
898 sii = SI_INFO(sih);
899 return sii->curidx;
902 /* return the core-type instantiation # of the current core */
903 uint
904 si_coreunit(si_t *sih)
906 si_info_t *sii;
907 uint idx;
908 uint coreid;
909 uint coreunit;
910 uint i;
912 sii = SI_INFO(sih);
913 coreunit = 0;
915 idx = sii->curidx;
917 ASSERT(GOODREGS(sii->curmap));
918 coreid = si_coreid(sih);
920 /* count the cores of our type */
921 for (i = 0; i < idx; i++)
922 if (sii->coreid[i] == coreid)
923 coreunit++;
925 return (coreunit);
928 uint
929 si_corevendor(si_t *sih)
931 if (CHIPTYPE(sih->socitype) == SOCI_SB)
932 return sb_corevendor(sih);
933 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
934 return ai_corevendor(sih);
935 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
936 return ub_corevendor(sih);
937 else {
938 ASSERT(0);
939 return 0;
943 bool
944 si_backplane64(si_t *sih)
946 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
949 uint
950 si_corerev(si_t *sih)
952 if (CHIPTYPE(sih->socitype) == SOCI_SB)
953 return sb_corerev(sih);
954 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
955 return ai_corerev(sih);
956 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
957 return ub_corerev(sih);
958 else {
959 ASSERT(0);
960 return 0;
964 /* return index of coreid or BADIDX if not found */
965 uint
966 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
968 si_info_t *sii;
969 uint found;
970 uint i;
972 sii = SI_INFO(sih);
974 found = 0;
976 for (i = 0; i < sii->numcores; i++)
977 if (sii->coreid[i] == coreid) {
978 if (found == coreunit)
979 return (i);
980 found++;
983 return (BADIDX);
986 /* return list of found cores */
987 uint
988 si_corelist(si_t *sih, uint coreid[])
990 si_info_t *sii;
992 sii = SI_INFO(sih);
994 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
995 return (sii->numcores);
998 /* return current register mapping */
999 void *
1000 si_coreregs(si_t *sih)
1002 si_info_t *sii;
1004 sii = SI_INFO(sih);
1005 ASSERT(GOODREGS(sii->curmap));
1007 return (sii->curmap);
1011 * This function changes logical "focus" to the indicated core;
1012 * must be called with interrupts off.
1013 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1015 void *
1016 si_setcore(si_t *sih, uint coreid, uint coreunit)
1018 uint idx;
1020 idx = si_findcoreidx(sih, coreid, coreunit);
1021 if (!GOODIDX(idx))
1022 return (NULL);
1024 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1025 return sb_setcoreidx(sih, idx);
1026 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1027 return ai_setcoreidx(sih, idx);
1028 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1029 return ub_setcoreidx(sih, idx);
1030 else {
1031 ASSERT(0);
1032 return NULL;
1036 void *
1037 si_setcoreidx(si_t *sih, uint coreidx)
1039 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1040 return sb_setcoreidx(sih, coreidx);
1041 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1042 return ai_setcoreidx(sih, coreidx);
1043 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1044 return ub_setcoreidx(sih, coreidx);
1045 else {
1046 ASSERT(0);
1047 return NULL;
1051 /* Turn off interrupt as required by sb_setcore, before switch core */
1052 void *
1053 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1055 void *cc;
1056 si_info_t *sii;
1058 sii = SI_INFO(sih);
1060 if (SI_FAST(sii)) {
1061 /* Overloading the origidx variable to remember the coreid,
1062 * this works because the core ids cannot be confused with
1063 * core indices.
1065 *origidx = coreid;
1066 if (coreid == CC_CORE_ID)
1067 return (void *)CCREGS_FAST(sii);
1068 else if (coreid == sih->buscoretype)
1069 return (void *)PCIEREGS(sii);
1071 INTR_OFF(sii, *intr_val);
1072 *origidx = sii->curidx;
1073 cc = si_setcore(sih, coreid, 0);
1074 ASSERT(cc != NULL);
1076 return cc;
1079 /* restore coreidx and restore interrupt */
1080 void
1081 si_restore_core(si_t *sih, uint coreid, uint intr_val)
1083 si_info_t *sii;
1085 sii = SI_INFO(sih);
1086 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1087 return;
1089 si_setcoreidx(sih, coreid);
1090 INTR_RESTORE(sii, intr_val);
1094 si_numaddrspaces(si_t *sih)
1096 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1097 return sb_numaddrspaces(sih);
1098 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1099 return ai_numaddrspaces(sih);
1100 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1101 return ub_numaddrspaces(sih);
1102 else {
1103 ASSERT(0);
1104 return 0;
1108 uint32
1109 si_addrspace(si_t *sih, uint asidx)
1111 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1112 return sb_addrspace(sih, asidx);
1113 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1114 return ai_addrspace(sih, asidx);
1115 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1116 return ub_addrspace(sih, asidx);
1117 else {
1118 ASSERT(0);
1119 return 0;
1123 uint32
1124 si_addrspacesize(si_t *sih, uint asidx)
1126 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1127 return sb_addrspacesize(sih, asidx);
1128 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1129 return ai_addrspacesize(sih, asidx);
1130 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1131 return ub_addrspacesize(sih, asidx);
1132 else {
1133 ASSERT(0);
1134 return 0;
1138 void
1139 si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
1141 /* Only supported for SOCI_AI */
1142 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1143 ai_coreaddrspaceX(sih, asidx, addr, size);
1144 else
1145 *size = 0;
1148 uint32
1149 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1151 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1152 return sb_core_cflags(sih, mask, val);
1153 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1154 return ai_core_cflags(sih, mask, val);
1155 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1156 return ub_core_cflags(sih, mask, val);
1157 else {
1158 ASSERT(0);
1159 return 0;
1163 void
1164 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1166 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1167 sb_core_cflags_wo(sih, mask, val);
1168 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1169 ai_core_cflags_wo(sih, mask, val);
1170 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1171 ub_core_cflags_wo(sih, mask, val);
1172 else
1173 ASSERT(0);
1176 uint32
1177 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1179 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1180 return sb_core_sflags(sih, mask, val);
1181 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1182 return ai_core_sflags(sih, mask, val);
1183 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1184 return ub_core_sflags(sih, mask, val);
1185 else {
1186 ASSERT(0);
1187 return 0;
1191 bool
1192 si_iscoreup(si_t *sih)
1194 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1195 return sb_iscoreup(sih);
1196 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1197 return ai_iscoreup(sih);
1198 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1199 return ub_iscoreup(sih);
1200 else {
1201 ASSERT(0);
1202 return FALSE;
1206 void
1207 si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1209 /* only for 4319, no requirement for SOCI_SB */
1210 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1211 ai_write_wrap_reg(sih, offset, val);
1213 else
1214 return;
1216 return;
1219 uint
1220 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1222 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1223 return sb_corereg(sih, coreidx, regoff, mask, val);
1224 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1225 return ai_corereg(sih, coreidx, regoff, mask, val);
1226 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1227 return ub_corereg(sih, coreidx, regoff, mask, val);
1228 else {
1229 ASSERT(0);
1230 return 0;
1234 void
1235 si_core_disable(si_t *sih, uint32 bits)
1237 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1238 sb_core_disable(sih, bits);
1239 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1240 ai_core_disable(sih, bits);
1241 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1242 ub_core_disable(sih, bits);
1245 void
1246 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1248 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1249 sb_core_reset(sih, bits, resetbits);
1250 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1251 ai_core_reset(sih, bits, resetbits);
1252 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1253 ub_core_reset(sih, bits, resetbits);
1256 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1258 si_corebist(si_t *sih)
1260 uint32 cflags;
1261 int result = 0;
1263 /* Read core control flags */
1264 cflags = si_core_cflags(sih, 0, 0);
1266 /* Set bist & fgc */
1267 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1269 /* Wait for bist done */
1270 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1272 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1273 result = BCME_ERROR;
1275 /* Reset core control flags */
1276 si_core_cflags(sih, 0xffff, cflags);
1278 return result;
1281 static uint32
1282 BCMINITFN(factor6)(uint32 x)
1284 switch (x) {
1285 case CC_F6_2: return 2;
1286 case CC_F6_3: return 3;
1287 case CC_F6_4: return 4;
1288 case CC_F6_5: return 5;
1289 case CC_F6_6: return 6;
1290 case CC_F6_7: return 7;
1291 default: return 0;
1295 /* calculate the speed the SI would run at given a set of clockcontrol values */
1296 uint32
1297 BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m)
1299 uint32 n1, n2, clock, m1, m2, m3, mc;
1301 n1 = n & CN_N1_MASK;
1302 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1304 if (pll_type == PLL_TYPE6) {
1305 if (m & CC_T6_MMASK)
1306 return CC_T6_M1;
1307 else
1308 return CC_T6_M0;
1309 } else if ((pll_type == PLL_TYPE1) ||
1310 (pll_type == PLL_TYPE3) ||
1311 (pll_type == PLL_TYPE4) ||
1312 (pll_type == PLL_TYPE7)) {
1313 n1 = factor6(n1);
1314 n2 += CC_F5_BIAS;
1315 } else if (pll_type == PLL_TYPE2) {
1316 n1 += CC_T2_BIAS;
1317 n2 += CC_T2_BIAS;
1318 ASSERT((n1 >= 2) && (n1 <= 7));
1319 ASSERT((n2 >= 5) && (n2 <= 23));
1320 } else if (pll_type == PLL_TYPE5) {
1321 return (100000000);
1322 } else
1323 ASSERT(0);
1324 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1325 if ((pll_type == PLL_TYPE3) ||
1326 (pll_type == PLL_TYPE7)) {
1327 clock = CC_CLOCK_BASE2 * n1 * n2;
1328 } else
1329 clock = CC_CLOCK_BASE1 * n1 * n2;
1331 if (clock == 0)
1332 return 0;
1334 m1 = m & CC_M1_MASK;
1335 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1336 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1337 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1339 if ((pll_type == PLL_TYPE1) ||
1340 (pll_type == PLL_TYPE3) ||
1341 (pll_type == PLL_TYPE4) ||
1342 (pll_type == PLL_TYPE7)) {
1343 m1 = factor6(m1);
1344 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1345 m2 += CC_F5_BIAS;
1346 else
1347 m2 = factor6(m2);
1348 m3 = factor6(m3);
1350 switch (mc) {
1351 case CC_MC_BYPASS: return (clock);
1352 case CC_MC_M1: return (clock / m1);
1353 case CC_MC_M1M2: return (clock / (m1 * m2));
1354 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
1355 case CC_MC_M1M3: return (clock / (m1 * m3));
1356 default: return (0);
1358 } else {
1359 ASSERT(pll_type == PLL_TYPE2);
1361 m1 += CC_T2_BIAS;
1362 m2 += CC_T2M2_BIAS;
1363 m3 += CC_T2_BIAS;
1364 ASSERT((m1 >= 2) && (m1 <= 7));
1365 ASSERT((m2 >= 3) && (m2 <= 10));
1366 ASSERT((m3 >= 2) && (m3 <= 7));
1368 if ((mc & CC_T2MC_M1BYP) == 0)
1369 clock /= m1;
1370 if ((mc & CC_T2MC_M2BYP) == 0)
1371 clock /= m2;
1372 if ((mc & CC_T2MC_M3BYP) == 0)
1373 clock /= m3;
1375 return (clock);
1379 uint32
1380 BCMINITFN(si_clock)(si_t *sih)
1382 si_info_t *sii;
1383 chipcregs_t *cc;
1384 uint32 n, m;
1385 uint idx;
1386 uint32 pll_type, rate;
1387 uint intr_val = 0;
1389 sii = SI_INFO(sih);
1390 INTR_OFF(sii, intr_val);
1391 if (PMUCTL_ENAB(sih)) {
1392 rate = si_pmu_si_clock(sih, sii->osh);
1393 goto exit;
1396 idx = sii->curidx;
1397 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1398 ASSERT(cc != NULL);
1400 n = R_REG(sii->osh, &cc->clockcontrol_n);
1401 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1402 if (pll_type == PLL_TYPE6)
1403 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1404 else if (pll_type == PLL_TYPE3)
1405 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1406 else
1407 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1409 /* calculate rate */
1410 rate = si_clock_rate(pll_type, n, m);
1412 if (pll_type == PLL_TYPE3)
1413 rate = rate / 2;
1415 /* switch back to previous core */
1416 si_setcoreidx(sih, idx);
1417 exit:
1418 INTR_RESTORE(sii, intr_val);
1420 return rate;
1423 uint32
1424 BCMINITFN(si_alp_clock)(si_t *sih)
1426 if (PMUCTL_ENAB(sih))
1427 return si_pmu_alp_clock(sih, si_osh(sih));
1429 return ALP_CLOCK;
1432 uint32
1433 BCMINITFN(si_ilp_clock)(si_t *sih)
1435 if (PMUCTL_ENAB(sih))
1436 return si_pmu_ilp_clock(sih, si_osh(sih));
1438 return ILP_CLOCK;
1441 /* set chip watchdog reset timer to fire in 'ticks' */
1442 void
1443 si_watchdog(si_t *sih, uint ticks)
1445 uint nb, maxt;
1447 if (PMUCTL_ENAB(sih)) {
1449 #if !defined(_CFE_) || defined(CFG_WL)
1450 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1451 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1452 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1453 si_setcore(sih, USB20D_CORE_ID, 0);
1454 si_core_disable(sih, 1);
1455 si_setcore(sih, CC_CORE_ID, 0);
1457 #endif /* !_CFE_ || CFG_WL */
1459 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
1460 nb = 32;
1461 else
1462 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1463 /* The mips compiler uses the sllv instruction,
1464 * so we specially handle the 32-bit case.
1466 if (nb == 32)
1467 maxt = 0xffffffff;
1468 else
1469 maxt = ((1 << nb) - 1);
1471 if (ticks == 1)
1472 ticks = 2;
1473 else if (ticks > maxt)
1474 ticks = maxt;
1476 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1477 } else {
1478 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1479 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1480 maxt = (1 << 28) - 1;
1481 if (ticks > maxt)
1482 ticks = maxt;
1484 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1488 /* trigger watchdog reset after ms milliseconds */
1489 void
1490 si_watchdog_ms(si_t *sih, uint32 ms)
1492 si_watchdog(sih, wd_msticks * ms);
1495 #if defined(BCMDBG_ERR) || defined(BCMASSERT_SUPPORT) || defined(BCMDBG_DUMP)
1496 bool
1497 si_taclear(si_t *sih, bool details)
1499 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1500 return sb_taclear(sih, details);
1501 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1502 return FALSE;
1503 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1504 return FALSE;
1505 else {
1506 ASSERT(0);
1507 return FALSE;
1510 #endif
1512 uint16
1513 BCMATTACHFN(si_d11_devid)(si_t *sih)
1515 si_info_t *sii = SI_INFO(sih);
1516 uint16 device;
1518 /* Fix device id for dual band BCM4328 */
1519 if (CHIPID(sih->chip) == BCM4328_CHIP_ID &&
1520 (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID))
1521 device = BCM4328_D11DUAL_ID;
1522 else {
1523 /* normal case: nvram variable with devpath->devid->wl0id */
1524 if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0)
1526 /* Get devid from OTP/SPROM depending on where the SROM is read */
1527 else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0)
1529 /* no longer support wl0id, but keep the code here for backward compatibility. */
1530 else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0)
1532 else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) {
1533 /* Chip specific conversion */
1534 if (sih->chippkg == BCM4712SMALL_PKG_ID)
1535 device = BCM4306_D11G_ID;
1536 else
1537 device = BCM4306_D11DUAL_ID;
1538 } else {
1539 /* ignore it */
1540 device = 0xffff;
1543 return device;
1547 BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
1548 uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
1549 uint8 *pciheader)
1551 uint16 vendor = 0xffff, device = 0xffff;
1552 uint8 class, subclass, progif = 0;
1553 uint8 header = PCI_HEADER_NORMAL;
1554 uint32 core = si_coreid(sih);
1556 /* Verify whether the function exists for the core */
1557 if (func >= (uint)(core == USB20H_CORE_ID ? 2 : 1))
1558 return BCME_ERROR;
1560 /* Known vendor translations */
1561 switch (si_corevendor(sih)) {
1562 case SB_VEND_BCM:
1563 case MFGID_BRCM:
1564 vendor = VENDOR_BROADCOM;
1565 break;
1566 default:
1567 return BCME_ERROR;
1570 /* Determine class based on known core codes */
1571 switch (core) {
1572 case ENET_CORE_ID:
1573 class = PCI_CLASS_NET;
1574 subclass = PCI_NET_ETHER;
1575 device = BCM47XX_ENET_ID;
1576 break;
1577 case GIGETH_CORE_ID:
1578 class = PCI_CLASS_NET;
1579 subclass = PCI_NET_ETHER;
1580 device = BCM47XX_GIGETH_ID;
1581 break;
1582 case GMAC_CORE_ID:
1583 class = PCI_CLASS_NET;
1584 subclass = PCI_NET_ETHER;
1585 device = BCM47XX_GMAC_ID;
1586 break;
1587 case SDRAM_CORE_ID:
1588 case MEMC_CORE_ID:
1589 case DMEMC_CORE_ID:
1590 case SOCRAM_CORE_ID:
1591 class = PCI_CLASS_MEMORY;
1592 subclass = PCI_MEMORY_RAM;
1593 device = (uint16)core;
1594 break;
1595 case PCI_CORE_ID:
1596 case PCIE_CORE_ID:
1597 class = PCI_CLASS_BRIDGE;
1598 subclass = PCI_BRIDGE_PCI;
1599 device = (uint16)core;
1600 header = PCI_HEADER_BRIDGE;
1601 break;
1602 case MIPS33_CORE_ID:
1603 case MIPS74K_CORE_ID:
1604 class = PCI_CLASS_CPU;
1605 subclass = PCI_CPU_MIPS;
1606 device = (uint16)core;
1607 break;
1608 case CODEC_CORE_ID:
1609 class = PCI_CLASS_COMM;
1610 subclass = PCI_COMM_MODEM;
1611 device = BCM47XX_V90_ID;
1612 break;
1613 case I2S_CORE_ID:
1614 class = PCI_CLASS_MMEDIA;
1615 subclass = PCI_MMEDIA_AUDIO;
1616 device = BCM47XX_AUDIO_ID;
1617 break;
1618 case USB_CORE_ID:
1619 case USB11H_CORE_ID:
1620 class = PCI_CLASS_SERIAL;
1621 subclass = PCI_SERIAL_USB;
1622 progif = 0x10; /* OHCI */
1623 device = BCM47XX_USBH_ID;
1624 break;
1625 case USB20H_CORE_ID:
1626 class = PCI_CLASS_SERIAL;
1627 subclass = PCI_SERIAL_USB;
1628 progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
1629 device = BCM47XX_USB20H_ID;
1630 header = 0x80; /* multifunction */
1631 break;
1632 case IPSEC_CORE_ID:
1633 class = PCI_CLASS_CRYPT;
1634 subclass = PCI_CRYPT_NETWORK;
1635 device = BCM47XX_IPSEC_ID;
1636 break;
1637 case ROBO_CORE_ID:
1638 /* Don't use class NETWORK, so wl/et won't attempt to recognize it */
1639 class = PCI_CLASS_COMM;
1640 subclass = PCI_COMM_OTHER;
1641 device = BCM47XX_ROBO_ID;
1642 break;
1643 case CC_CORE_ID:
1644 class = PCI_CLASS_MEMORY;
1645 subclass = PCI_MEMORY_FLASH;
1646 device = (uint16)core;
1647 break;
1648 case SATAXOR_CORE_ID:
1649 class = PCI_CLASS_XOR;
1650 subclass = PCI_XOR_QDMA;
1651 device = BCM47XX_SATAXOR_ID;
1652 break;
1653 case ATA100_CORE_ID:
1654 class = PCI_CLASS_DASDI;
1655 subclass = PCI_DASDI_IDE;
1656 device = BCM47XX_ATA100_ID;
1657 break;
1658 case USB11D_CORE_ID:
1659 class = PCI_CLASS_SERIAL;
1660 subclass = PCI_SERIAL_USB;
1661 device = BCM47XX_USBD_ID;
1662 break;
1663 case USB20D_CORE_ID:
1664 class = PCI_CLASS_SERIAL;
1665 subclass = PCI_SERIAL_USB;
1666 device = BCM47XX_USB20D_ID;
1667 break;
1668 case D11_CORE_ID:
1669 class = PCI_CLASS_NET;
1670 subclass = PCI_NET_OTHER;
1671 device = si_d11_devid(sih);
1672 break;
1674 default:
1675 class = subclass = progif = 0xff;
1676 device = (uint16)core;
1677 break;
1680 *pcivendor = vendor;
1681 *pcidevice = device;
1682 *pciclass = class;
1683 *pcisubclass = subclass;
1684 *pciprogif = progif;
1685 *pciheader = header;
1687 return 0;
1690 #if defined(BCMDBG) || defined(BCMDBG_DUMP)
1691 /* print interesting sbconfig registers */
1692 void
1693 si_dumpregs(si_t *sih, struct bcmstrbuf *b)
1695 si_info_t *sii;
1696 uint origidx, intr_val = 0;
1698 sii = SI_INFO(sih);
1699 origidx = sii->curidx;
1701 INTR_OFF(sii, intr_val);
1702 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1703 sb_dumpregs(sih, b);
1704 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1705 ai_dumpregs(sih, b);
1706 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1707 ub_dumpregs(sih, b);
1708 else
1709 ASSERT(0);
1711 si_setcoreidx(sih, origidx);
1712 INTR_RESTORE(sii, intr_val);
1714 #endif /* BCMDBG || BCMDBG_DUMP */
1716 #ifdef BCMDBG
1717 void
1718 si_view(si_t *sih, bool verbose)
1720 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1721 sb_view(sih, verbose);
1722 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1723 ai_view(sih, verbose);
1724 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1725 ub_view(sih, verbose);
1726 else
1727 ASSERT(0);
1730 void
1731 si_viewall(si_t *sih, bool verbose)
1733 si_info_t *sii;
1734 uint curidx, i;
1735 uint intr_val = 0;
1737 sii = SI_INFO(sih);
1738 curidx = sii->curidx;
1740 INTR_OFF(sii, intr_val);
1741 SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores));
1742 for (i = 0; i < sii->numcores; i++) {
1743 si_setcoreidx(sih, i);
1744 si_view(sih, verbose);
1747 si_setcoreidx(sih, curidx);
1748 INTR_RESTORE(sii, intr_val);
1750 #endif /* BCMDBG */
1752 /* return the slow clock source - LPO, XTAL, or PCI */
1753 static uint
1754 si_slowclk_src(si_info_t *sii)
1756 chipcregs_t *cc;
1758 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1760 if (sii->pub.ccrev < 6) {
1761 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1762 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1763 PCI_CFG_GPIO_SCS))
1764 return (SCC_SS_PCI);
1765 else
1766 return (SCC_SS_XTAL);
1767 } else if (sii->pub.ccrev < 10) {
1768 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1769 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1770 } else /* Insta-clock */
1771 return (SCC_SS_XTAL);
1774 /* return the ILP (slowclock) min or max frequency */
1775 static uint
1776 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1778 uint32 slowclk;
1779 uint div;
1781 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1783 /* shouldn't be here unless we've established the chip has dynamic clk control */
1784 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1786 slowclk = si_slowclk_src(sii);
1787 if (sii->pub.ccrev < 6) {
1788 if (slowclk == SCC_SS_PCI)
1789 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1790 else
1791 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1792 } else if (sii->pub.ccrev < 10) {
1793 div = 4 *
1794 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1795 if (slowclk == SCC_SS_LPO)
1796 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1797 else if (slowclk == SCC_SS_XTAL)
1798 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1799 else if (slowclk == SCC_SS_PCI)
1800 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1801 else
1802 ASSERT(0);
1803 } else {
1804 /* Chipc rev 10 is InstaClock */
1805 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1806 div = 4 * (div + 1);
1807 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1809 return (0);
1812 static void
1813 BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs)
1815 chipcregs_t *cc = (chipcregs_t *)chipcregs;
1816 uint slowmaxfreq, pll_delay, slowclk;
1817 uint pll_on_delay, fref_sel_delay;
1819 pll_delay = PLL_DELAY;
1821 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1822 * since the xtal will also be powered down by dynamic clk control logic.
1825 slowclk = si_slowclk_src(sii);
1826 if (slowclk != SCC_SS_XTAL)
1827 pll_delay += XTAL_ON_DELAY;
1829 /* Starting with 4318 it is ILP that is used for the delays */
1830 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1832 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1833 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1835 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1836 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1839 /* initialize power control delay registers */
1840 void
1841 BCMINITFN(si_clkctl_init)(si_t *sih)
1843 si_info_t *sii;
1844 uint origidx = 0;
1845 chipcregs_t *cc;
1846 bool fast;
1848 if (!CCCTL_ENAB(sih))
1849 return;
1851 sii = SI_INFO(sih);
1852 fast = SI_FAST(sii);
1853 if (!fast) {
1854 origidx = sii->curidx;
1855 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1856 return;
1857 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1858 return;
1859 ASSERT(cc != NULL);
1861 /* set all Instaclk chip ILP to 1 MHz */
1862 if (sih->ccrev >= 10)
1863 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1864 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1866 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1868 if (!fast)
1869 si_setcoreidx(sih, origidx);
1872 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1873 uint16
1874 BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih)
1876 si_info_t *sii;
1877 uint origidx = 0;
1878 chipcregs_t *cc;
1879 uint slowminfreq;
1880 uint16 fpdelay;
1881 uint intr_val = 0;
1882 bool fast;
1884 sii = SI_INFO(sih);
1885 if (PMUCTL_ENAB(sih)) {
1886 INTR_OFF(sii, intr_val);
1887 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1888 INTR_RESTORE(sii, intr_val);
1889 return fpdelay;
1892 if (!CCCTL_ENAB(sih))
1893 return 0;
1895 fast = SI_FAST(sii);
1896 fpdelay = 0;
1897 if (!fast) {
1898 origidx = sii->curidx;
1899 INTR_OFF(sii, intr_val);
1900 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1901 goto done;
1903 else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1904 goto done;
1905 ASSERT(cc != NULL);
1907 slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1908 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1909 (slowminfreq - 1)) / slowminfreq;
1911 done:
1912 if (!fast) {
1913 si_setcoreidx(sih, origidx);
1914 INTR_RESTORE(sii, intr_val);
1916 return fpdelay;
1919 /* turn primary xtal and/or pll off/on */
1921 si_clkctl_xtal(si_t *sih, uint what, bool on)
1923 si_info_t *sii;
1924 uint32 in, out, outen;
1926 sii = SI_INFO(sih);
1928 switch (BUSTYPE(sih->bustype)) {
1931 case PCMCIA_BUS:
1932 return (0);
1935 case PCI_BUS:
1936 /* pcie core doesn't have any mapping to control the xtal pu */
1937 if (PCIE(sii))
1938 return -1;
1940 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
1941 out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
1942 outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32));
1945 * Avoid glitching the clock if GPRS is already using it.
1946 * We can't actually read the state of the PLLPD so we infer it
1947 * by the value of XTAL_PU which *is* readable via gpioin.
1949 if (on && (in & PCI_CFG_GPIO_XTAL))
1950 return (0);
1952 if (what & XTAL)
1953 outen |= PCI_CFG_GPIO_XTAL;
1954 if (what & PLL)
1955 outen |= PCI_CFG_GPIO_PLL;
1957 if (on) {
1958 /* turn primary xtal on */
1959 if (what & XTAL) {
1960 out |= PCI_CFG_GPIO_XTAL;
1961 if (what & PLL)
1962 out |= PCI_CFG_GPIO_PLL;
1963 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1964 sizeof(uint32), out);
1965 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1966 sizeof(uint32), outen);
1967 OSL_DELAY(XTAL_ON_DELAY);
1970 /* turn pll on */
1971 if (what & PLL) {
1972 out &= ~PCI_CFG_GPIO_PLL;
1973 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1974 sizeof(uint32), out);
1975 OSL_DELAY(2000);
1977 } else {
1978 if (what & XTAL)
1979 out &= ~PCI_CFG_GPIO_XTAL;
1980 if (what & PLL)
1981 out |= PCI_CFG_GPIO_PLL;
1982 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out);
1983 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32),
1984 outen);
1986 return (0);
1987 default:
1988 return (-1);
1993 * clock control policy function throught chipcommon
1995 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1996 * returns true if we are forcing fast clock
1997 * this is a wrapper over the next internal function
1998 * to allow flexible policy settings for outside caller
2000 bool
2001 si_clkctl_cc(si_t *sih, uint mode)
2003 si_info_t *sii;
2005 sii = SI_INFO(sih);
2007 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2008 if (sih->ccrev < 6)
2009 return FALSE;
2011 if (PCI_FORCEHT(sii))
2012 return (mode == CLK_FAST);
2014 return _si_clkctl_cc(sii, mode);
2017 /* clk control mechanism through chipcommon, no policy checking */
2018 static bool
2019 _si_clkctl_cc(si_info_t *sii, uint mode)
2021 uint origidx = 0;
2022 chipcregs_t *cc;
2023 uint32 scc;
2024 uint intr_val = 0;
2025 bool fast = SI_FAST(sii);
2027 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2028 if (sii->pub.ccrev < 6)
2029 return (FALSE);
2031 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
2032 ASSERT(sii->pub.ccrev != 10);
2034 if (!fast) {
2035 INTR_OFF(sii, intr_val);
2036 origidx = sii->curidx;
2038 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
2039 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
2040 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
2041 goto done;
2043 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
2044 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
2045 goto done;
2046 ASSERT(cc != NULL);
2048 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
2049 goto done;
2051 switch (mode) {
2052 case CLK_FAST: /* FORCEHT, fast (pll) clock */
2053 if (sii->pub.ccrev < 10) {
2054 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2055 si_clkctl_xtal(&sii->pub, XTAL, ON);
2056 SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
2057 } else if (sii->pub.ccrev < 20) {
2058 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
2059 } else {
2060 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
2063 /* wait for the PLL */
2064 if (PMUCTL_ENAB(&sii->pub)) {
2065 uint32 htavail = CCS_HTAVAIL;
2066 if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2067 htavail = CCS0_HTAVAIL;
2068 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0),
2069 PMU_MAX_TRANSITION_DLY);
2070 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
2071 } else {
2072 OSL_DELAY(PLL_DELAY);
2074 break;
2076 case CLK_DYNAMIC: /* enable dynamic clock control */
2077 if (sii->pub.ccrev < 10) {
2078 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
2079 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
2080 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
2081 scc |= SCC_XC;
2082 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
2084 /* for dynamic control, we have to release our xtal_pu "force on" */
2085 if (scc & SCC_XC)
2086 si_clkctl_xtal(&sii->pub, XTAL, OFF);
2087 } else if (sii->pub.ccrev < 20) {
2088 /* Instaclock */
2089 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
2090 } else {
2091 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
2093 break;
2095 default:
2096 ASSERT(0);
2099 done:
2100 if (!fast) {
2101 si_setcoreidx(&sii->pub, origidx);
2102 INTR_RESTORE(sii, intr_val);
2104 return (mode == CLK_FAST);
2107 /* Build device path. Support SI, PCI, and JTAG for now. */
2109 BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size)
2111 int slen;
2113 ASSERT(path != NULL);
2114 ASSERT(size >= SI_DEVPATH_BUFSZ);
2116 if (!path || size <= 0)
2117 return -1;
2119 switch (BUSTYPE(sih->bustype)) {
2120 case SI_BUS:
2121 case JTAG_BUS:
2122 slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih));
2123 break;
2124 case PCI_BUS:
2125 ASSERT((SI_INFO(sih))->osh != NULL);
2126 slen = snprintf(path, (size_t)size, "pci/%u/%u/",
2127 OSL_PCI_BUS((SI_INFO(sih))->osh),
2128 OSL_PCI_SLOT((SI_INFO(sih))->osh));
2129 break;
2130 case PCMCIA_BUS:
2131 SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
2132 SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
2133 slen = snprintf(path, (size_t)size, "pc/1/1/");
2134 break;
2135 default:
2136 slen = -1;
2137 ASSERT(0);
2138 break;
2141 if (slen < 0 || slen >= size) {
2142 path[0] = '\0';
2143 return -1;
2146 return 0;
2149 char *
2150 BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name)
2152 char pathname[SI_DEVPATH_BUFSZ + 32];
2153 char devpath[SI_DEVPATH_BUFSZ + 32];
2154 char *p;
2155 int idx;
2156 int len;
2158 /* try to get compact devpath if it exist */
2159 if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) {
2160 len = strlen(devpath);
2161 devpath[len - 1] = '\0';
2162 for (idx = 0; idx < SI_MAXCORES; idx++) {
2163 snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx);
2164 if ((p = getvar(NULL, pathname)) == NULL)
2165 continue;
2167 if (strncmp(p, devpath, len) == 0) {
2168 snprintf(varname, var_len, "%d:%s", idx, name);
2169 return varname;
2174 return NULL;
2177 /* Get a variable, but only if it has a devpath prefix */
2178 char *
2179 BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name)
2181 char varname[SI_DEVPATH_BUFSZ + 32];
2182 char *val;
2184 si_devpathvar(sih, varname, sizeof(varname), name);
2186 if ((val = getvar(NULL, varname)) != NULL)
2187 return val;
2189 /* try to get compact devpath if it exist */
2190 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2191 return NULL;
2193 return (getvar(NULL, varname));
2196 /* Get a variable, but only if it has a devpath prefix */
2198 BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name)
2200 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
2201 return (getintvar(NULL, name));
2202 #else
2203 char varname[SI_DEVPATH_BUFSZ + 32];
2204 int val;
2206 si_devpathvar(sih, varname, sizeof(varname), name);
2208 if ((val = getintvar(NULL, varname)) != 0)
2209 return val;
2211 /* try to get compact devpath if it exist */
2212 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2213 return 0;
2215 return (getintvar(NULL, varname));
2216 #endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
2219 #ifndef DONGLEBUILD
2220 char *
2221 si_getnvramflvar(si_t *sih, const char *name)
2223 return (getvar(NULL, name));
2225 #endif /* DONGLEBUILD */
2227 /* Concatenate the dev path with a varname into the given 'var' buffer
2228 * and return the 'var' pointer.
2229 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
2230 * On overflow, the first char will be set to '\0'.
2232 static char *
2233 BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name)
2235 uint path_len;
2237 if (!var || len <= 0)
2238 return var;
2240 if (si_devpath(sih, var, len) == 0) {
2241 path_len = strlen(var);
2243 if (strlen(name) + 1 > (uint)(len - path_len))
2244 var[0] = '\0';
2245 else
2246 strncpy(var + path_len, name, len - path_len - 1);
2249 return var;
2253 uint32
2254 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
2256 si_info_t *sii;
2258 sii = SI_INFO(sih);
2260 if (!PCIE(sii)) {
2261 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2262 return 0;
2265 return pcicore_pciereg(sii->pch, offset, mask, val, type);
2268 uint32
2269 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
2271 si_info_t *sii;
2273 sii = SI_INFO(sih);
2275 if (!PCIE(sii)) {
2276 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2277 return 0;
2280 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
2284 /* return TRUE if PCIE capability exists in the pci config space */
2285 static bool
2286 si_ispcie(si_info_t *sii)
2288 uint8 cap_ptr;
2290 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2291 return FALSE;
2293 cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL);
2294 if (!cap_ptr)
2295 return FALSE;
2297 return TRUE;
2300 /* Wake-on-wireless-LAN (WOWL) support functions */
2301 /* Enable PME generation and disable clkreq */
2302 void
2303 si_pci_pmeen(si_t *sih)
2305 si_info_t *sii;
2307 sii = SI_INFO(sih);
2309 pcicore_pmeen(sii->pch);
2312 /* Return TRUE if PME status is set */
2313 bool
2314 si_pci_pmestat(si_t *sih)
2316 si_info_t *sii;
2318 sii = SI_INFO(sih);
2320 return pcicore_pmestat(sii->pch);
2323 /* Disable PME generation, clear the PME status bit if set */
2324 void
2325 si_pci_pmeclr(si_t *sih)
2327 si_info_t *sii;
2329 sii = SI_INFO(sih);
2331 pcicore_pmeclr(sii->pch);
2334 /* initialize the pcmcia core */
2335 void
2336 si_pcmcia_init(si_t *sih)
2338 si_info_t *sii;
2339 uint8 cor = 0;
2341 sii = SI_INFO(sih);
2343 /* enable d11 mac interrupts */
2344 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2345 cor |= COR_IRQEN | COR_FUNEN;
2346 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2351 bool
2352 BCMATTACHFN(si_pci_war16165)(si_t *sih)
2354 si_info_t *sii;
2356 sii = SI_INFO(sih);
2358 return (PCI(sii) && (sih->buscorerev <= 10));
2361 /* Disable pcie_war_ovr for some platforms (sigh!)
2362 * This is for boards that have BFL2_PCIEWAR_OVR set
2363 * but are in systems that still want the benefits of ASPM
2364 * Note that this should be done AFTER si_doattach
2366 void
2367 si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
2369 si_info_t *sii;
2371 sii = SI_INFO(sih);
2373 if (!PCIE(sii))
2374 return;
2376 pcie_war_ovr_aspm_update(sii->pch, aspm);
2379 void
2380 si_pcie_power_save_enable(si_t *sih, bool enable)
2382 si_info_t *sii;
2384 sii = SI_INFO(sih);
2386 if (!PCIE(sii))
2387 return;
2389 pcie_power_save_enable(sii->pch, enable);
2392 void
2393 si_pcie_set_request_size(si_t *sih, uint16 size)
2395 si_info_t *sii;
2397 sii = SI_INFO(sih);
2399 if (!PCIE(sii))
2400 return;
2402 pcie_set_request_size(sii->pch, size);
2405 uint16
2406 si_pcie_get_request_size(si_t *sih)
2408 si_info_t *sii;
2410 sii = SI_INFO(sih);
2412 if (!PCIE(sii))
2413 return (0);
2415 return pcie_get_request_size(sii->pch);
2418 /* back door for other module to override chippkg */
2419 void
2420 si_chippkg_set(si_t *sih, uint val)
2422 si_info_t *sii;
2424 sii = SI_INFO(sih);
2426 sii->pub.chippkg = val;
2429 void
2430 BCMINITFN(si_pci_up)(si_t *sih)
2432 si_info_t *sii;
2434 sii = SI_INFO(sih);
2436 /* if not pci bus, we're done */
2437 if (BUSTYPE(sih->bustype) != PCI_BUS)
2438 return;
2440 if (PCI_FORCEHT(sii))
2441 _si_clkctl_cc(sii, CLK_FAST);
2443 if (PCIE(sii)) {
2444 pcicore_up(sii->pch, SI_PCIUP);
2445 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
2446 (CHIPID(sih->chip) == BCM4312_CHIP_ID))
2447 sb_set_initiator_to((void *)sii, 0x3,
2448 si_findcoreidx((void *)sii, D11_CORE_ID, 0));
2452 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2453 void
2454 BCMUNINITFN(si_pci_sleep)(si_t *sih)
2456 si_info_t *sii;
2458 sii = SI_INFO(sih);
2460 pcicore_sleep(sii->pch);
2463 /* Unconfigure and/or apply various WARs when going down */
2464 void
2465 BCMINITFN(si_pci_down)(si_t *sih)
2467 si_info_t *sii;
2469 sii = SI_INFO(sih);
2471 /* if not pci bus, we're done */
2472 if (BUSTYPE(sih->bustype) != PCI_BUS)
2473 return;
2475 /* release FORCEHT since chip is going to "down" state */
2476 if (PCI_FORCEHT(sii))
2477 _si_clkctl_cc(sii, CLK_DYNAMIC);
2479 pcicore_down(sii->pch, SI_PCIDOWN);
2483 * Configure the pci core for pci client (NIC) action
2484 * coremask is the bitvec of cores by index to be enabled.
2486 void
2487 BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask)
2489 si_info_t *sii;
2490 sbpciregs_t *pciregs = NULL;
2491 uint32 siflag = 0, w;
2492 uint idx = 0;
2494 sii = SI_INFO(sih);
2496 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2497 return;
2499 ASSERT(PCI(sii) || PCIE(sii));
2500 ASSERT(sii->pub.buscoreidx != BADIDX);
2502 if (PCI(sii)) {
2503 /* get current core index */
2504 idx = sii->curidx;
2506 /* we interrupt on this backplane flag number */
2507 siflag = si_flag(sih);
2509 /* switch over to pci core */
2510 pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx);
2514 * Enable sb->pci interrupts. Assume
2515 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2517 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2518 /* pci config write to set this core bit in PCIIntMask */
2519 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2520 w |= (coremask << PCI_SBIM_SHIFT);
2521 #ifdef USER_MODE
2522 /* User mode operate with interrupt disabled */
2523 w &= !(coremask << PCI_SBIM_SHIFT);
2524 #endif
2525 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2526 } else {
2527 /* set sbintvec bit for our flag number */
2528 si_setint(sih, siflag);
2531 if (PCI(sii)) {
2532 OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST));
2533 if (sii->pub.buscorerev >= 11) {
2534 OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
2535 w = R_REG(sii->osh, &pciregs->clkrun);
2536 W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL));
2537 w = R_REG(sii->osh, &pciregs->clkrun);
2540 /* switch back to previous core */
2541 si_setcoreidx(sih, idx);
2545 uint8
2546 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2548 si_info_t *sii;
2550 sii = SI_INFO(sih);
2552 if (!(PCIE(sii)))
2553 return 0;
2554 return pcie_clkreq(sii->pch, mask, val);
2557 uint32
2558 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2560 si_info_t *sii;
2562 sii = SI_INFO(sih);
2564 if (!PCIE(sii))
2565 return 0;
2567 return pcie_lcreg(sii->pch, mask, val);
2570 /* indirect way to read pcie config regs */
2571 uint
2572 si_pcie_readreg(void *sih, uint addrtype, uint offset)
2574 return pcie_readreg(((si_info_t *)sih)->osh, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
2575 addrtype, offset);
2580 * Fixup SROMless PCI device's configuration.
2581 * The current core may be changed upon return.
2584 si_pci_fixcfg(si_t *sih)
2586 uint origidx, pciidx;
2587 sbpciregs_t *pciregs = NULL;
2588 sbpcieregs_t *pcieregs = NULL;
2589 void *regs = NULL;
2590 uint16 val16, *reg16 = NULL;
2591 uint32 w;
2593 si_info_t *sii = SI_INFO(sih);
2595 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2597 if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) {
2598 w = (CHIPREV(sii->pub.chiprev) == 0) ?
2599 CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT;
2600 si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w);
2603 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2604 /* save the current index */
2605 origidx = si_coreidx(&sii->pub);
2607 /* check 'pi' is correct and fix it if not */
2608 if (sii->pub.buscoretype == PCIE_CORE_ID) {
2609 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2610 regs = pcieregs;
2611 ASSERT(pcieregs != NULL);
2612 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2613 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
2614 pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
2615 regs = pciregs;
2616 ASSERT(pciregs != NULL);
2617 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2619 pciidx = si_coreidx(&sii->pub);
2620 val16 = R_REG(sii->osh, reg16);
2621 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
2622 val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
2623 W_REG(sii->osh, reg16, val16);
2626 /* restore the original index */
2627 si_setcoreidx(&sii->pub, origidx);
2629 pcicore_hwup(sii->pch);
2630 return 0;
2633 #if defined(BCMDBG_DUMP)
2635 void
2636 si_dump(si_t *sih, struct bcmstrbuf *b)
2638 si_info_t *sii;
2639 uint i;
2641 sii = SI_INFO(sih);
2643 bcm_bprintf(b, "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n",
2644 sii, sih->chip, sih->chiprev, sih->boardtype, sih->boardvendor, sih->bustype);
2645 bcm_bprintf(b, "osh %p curmap %p\n",
2646 sii->osh, sii->curmap);
2647 if (CHIPTYPE(sih->socitype) == SOCI_SB)
2648 bcm_bprintf(b, "sonicsrev %d ", sih->socirev);
2649 bcm_bprintf(b, "ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n",
2650 sih->ccrev, sih->buscoretype, sih->buscorerev, sii->curidx);
2652 #ifdef BCMDBG
2653 if ((BUSTYPE(sih->bustype) == PCI_BUS) && (sii->pch))
2654 pcicore_dump(sii->pch, b);
2655 #endif
2657 bcm_bprintf(b, "cores: ");
2658 for (i = 0; i < sii->numcores; i++)
2659 bcm_bprintf(b, "0x%x ", sii->coreid[i]);
2660 bcm_bprintf(b, "\n");
2663 void
2664 si_ccreg_dump(si_t *sih, struct bcmstrbuf *b)
2666 si_info_t *sii;
2667 uint origidx;
2668 uint i, intr_val = 0;
2669 chipcregs_t *cc;
2671 sii = SI_INFO(sih);
2672 origidx = sii->curidx;
2674 /* only support corerev 22 for now */
2675 if (sih->ccrev != 23)
2676 return;
2678 INTR_OFF(sii, intr_val);
2680 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2682 bcm_bprintf(b, "\n===cc(rev %d) registers(offset val)===\n", sih->ccrev);
2683 for (i = 0; i <= 0xc4; i += 4) {
2684 if (i == 0x4c) {
2685 bcm_bprintf(b, "\n");
2686 continue;
2688 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2691 bcm_bprintf(b, "\n");
2693 for (i = 0x1e0; i <= 0x1e4; i += 4) {
2694 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2696 bcm_bprintf(b, "\n");
2698 if (sih->cccaps & CC_CAP_PMU) {
2699 for (i = 0x600; i <= 0x660; i += 4) {
2700 bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2703 bcm_bprintf(b, "\n");
2705 si_setcoreidx(sih, origidx);
2706 INTR_RESTORE(sii, intr_val);
2709 /* dump dynamic clock control related registers */
2710 void
2711 si_clkctl_dump(si_t *sih, struct bcmstrbuf *b)
2713 si_info_t *sii;
2714 chipcregs_t *cc;
2715 uint origidx;
2716 uint intr_val = 0;
2718 if (!(sih->cccaps & CC_CAP_PWR_CTL))
2719 return;
2721 sii = SI_INFO(sih);
2722 INTR_OFF(sii, intr_val);
2723 origidx = sii->curidx;
2724 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2725 goto done;
2727 bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ",
2728 cc->pll_on_delay, cc->fref_sel_delay);
2729 if ((sih->ccrev >= 6) && (sih->ccrev < 10))
2730 bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl);
2731 if (sih->ccrev >= 10) {
2732 bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl);
2733 bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch);
2736 if (BUSTYPE(sih->bustype) == PCI_BUS)
2737 bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ",
2738 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)),
2739 OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32)));
2741 if (sih->cccaps & CC_CAP_PMU) {
2742 /* dump some PMU register ? */
2744 bcm_bprintf(b, "\n");
2746 si_setcoreidx(sih, origidx);
2747 done:
2748 INTR_RESTORE(sii, intr_val);
2752 si_dump_pcieregs(si_t *sih, struct bcmstrbuf *b)
2754 si_info_t *sii;
2756 sii = SI_INFO(sih);
2758 if (!PCIE(sii))
2759 return BCME_ERROR;
2761 return pcicore_dump_pcieregs(sii->pch, b);
2765 si_gpiodump(si_t *sih, struct bcmstrbuf *b)
2767 si_info_t *sii;
2768 uint origidx;
2769 uint intr_val = 0;
2770 chipcregs_t *cc;
2772 sii = SI_INFO(sih);
2774 INTR_OFF(sii, intr_val);
2776 origidx = si_coreidx(sih);
2778 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2779 ASSERT(cc);
2781 bcm_bprintf(b, "GPIOregs\t");
2783 bcm_bprintf(b, "gpioin 0x%x ", R_REG(sii->osh, &cc->gpioin));
2784 bcm_bprintf(b, "gpioout 0x%x ", R_REG(sii->osh, &cc->gpioout));
2785 bcm_bprintf(b, "gpioouten 0x%x ", R_REG(sii->osh, &cc->gpioouten));
2786 bcm_bprintf(b, "gpiocontrol 0x%x ", R_REG(sii->osh, &cc->gpiocontrol));
2787 bcm_bprintf(b, "gpiointpolarity 0x%x ", R_REG(sii->osh, &cc->gpiointpolarity));
2788 bcm_bprintf(b, "gpiointmask 0x%x ", R_REG(sii->osh, &cc->gpiointmask));
2790 if (sii->pub.ccrev >= 16) {
2791 bcm_bprintf(b, "gpiotimerval 0x%x ", R_REG(sii->osh, &cc->gpiotimerval));
2792 bcm_bprintf(b, "gpiotimeroutmask 0x%x", R_REG(sii->osh, &cc->gpiotimeroutmask));
2794 bcm_bprintf(b, "\n");
2796 /* restore the original index */
2797 si_setcoreidx(sih, origidx);
2799 INTR_RESTORE(sii, intr_val);
2800 return 0;
2803 #endif
2805 /* change logical "focus" to the gpio core for optimized access */
2806 void *
2807 si_gpiosetcore(si_t *sih)
2809 return (si_setcoreidx(sih, SI_CC_IDX));
2812 /* mask&set gpiocontrol bits */
2813 uint32
2814 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2816 uint regoff;
2818 regoff = 0;
2820 /* gpios could be shared on router platforms
2821 * ignore reservation if it's high priority (e.g., test apps)
2823 if ((priority != GPIO_HI_PRIORITY) &&
2824 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2825 mask = priority ? (si_gpioreservation & mask) :
2826 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2827 val &= mask;
2830 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2831 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2834 /* mask&set gpio output enable bits */
2835 uint32
2836 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2838 uint regoff;
2840 regoff = 0;
2842 /* gpios could be shared on router platforms
2843 * ignore reservation if it's high priority (e.g., test apps)
2845 if ((priority != GPIO_HI_PRIORITY) &&
2846 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2847 mask = priority ? (si_gpioreservation & mask) :
2848 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2849 val &= mask;
2852 regoff = OFFSETOF(chipcregs_t, gpioouten);
2853 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2856 /* mask&set gpio output bits */
2857 uint32
2858 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2860 uint regoff;
2862 regoff = 0;
2864 /* gpios could be shared on router platforms
2865 * ignore reservation if it's high priority (e.g., test apps)
2867 if ((priority != GPIO_HI_PRIORITY) &&
2868 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2869 mask = priority ? (si_gpioreservation & mask) :
2870 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2871 val &= mask;
2874 regoff = OFFSETOF(chipcregs_t, gpioout);
2875 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2878 /* reserve one gpio */
2879 uint32
2880 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2882 si_info_t *sii;
2884 sii = SI_INFO(sih);
2886 /* only cores on SI_BUS share GPIO's and only applcation users need to
2887 * reserve/release GPIO
2889 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2890 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2891 return 0xffffffff;
2893 /* make sure only one bit is set */
2894 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2895 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2896 return 0xffffffff;
2899 /* already reserved */
2900 if (si_gpioreservation & gpio_bitmask)
2901 return 0xffffffff;
2902 /* set reservation */
2903 si_gpioreservation |= gpio_bitmask;
2905 return si_gpioreservation;
2908 /* release one gpio */
2910 * releasing the gpio doesn't change the current value on the GPIO last write value
2911 * persists till some one overwrites it
2914 uint32
2915 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2917 si_info_t *sii;
2919 sii = SI_INFO(sih);
2921 /* only cores on SI_BUS share GPIO's and only applcation users need to
2922 * reserve/release GPIO
2924 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2925 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2926 return 0xffffffff;
2928 /* make sure only one bit is set */
2929 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2930 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2931 return 0xffffffff;
2934 /* already released */
2935 if (!(si_gpioreservation & gpio_bitmask))
2936 return 0xffffffff;
2938 /* clear reservation */
2939 si_gpioreservation &= ~gpio_bitmask;
2941 return si_gpioreservation;
2944 /* return the current gpioin register value */
2945 uint32
2946 si_gpioin(si_t *sih)
2948 si_info_t *sii;
2949 uint regoff;
2951 sii = SI_INFO(sih);
2952 regoff = 0;
2954 regoff = OFFSETOF(chipcregs_t, gpioin);
2955 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
2958 /* mask&set gpio interrupt polarity bits */
2959 uint32
2960 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2962 si_info_t *sii;
2963 uint regoff;
2965 sii = SI_INFO(sih);
2966 regoff = 0;
2968 /* gpios could be shared on router platforms */
2969 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2970 mask = priority ? (si_gpioreservation & mask) :
2971 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2972 val &= mask;
2975 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2976 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2979 /* mask&set gpio interrupt mask bits */
2980 uint32
2981 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2983 si_info_t *sii;
2984 uint regoff;
2986 sii = SI_INFO(sih);
2987 regoff = 0;
2989 /* gpios could be shared on router platforms */
2990 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2991 mask = priority ? (si_gpioreservation & mask) :
2992 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2993 val &= mask;
2996 regoff = OFFSETOF(chipcregs_t, gpiointmask);
2997 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3000 /* assign the gpio to an led */
3001 uint32
3002 si_gpioled(si_t *sih, uint32 mask, uint32 val)
3004 si_info_t *sii;
3006 sii = SI_INFO(sih);
3007 if (sih->ccrev < 16)
3008 return 0xffffffff;
3010 /* gpio led powersave reg */
3011 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
3014 /* mask&set gpio timer val */
3015 uint32
3016 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
3018 si_info_t *sii;
3020 sii = SI_INFO(sih);
3022 if (sih->ccrev < 16)
3023 return 0xffffffff;
3025 return (si_corereg(sih, SI_CC_IDX,
3026 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
3029 uint32
3030 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
3032 si_info_t *sii;
3033 uint offs;
3035 sii = SI_INFO(sih);
3036 if (sih->ccrev < 20)
3037 return 0xffffffff;
3039 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
3040 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3043 uint32
3044 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
3046 si_info_t *sii;
3047 uint offs;
3049 sii = SI_INFO(sih);
3050 if (sih->ccrev < 11)
3051 return 0xffffffff;
3053 if (regtype == GPIO_REGEVT)
3054 offs = OFFSETOF(chipcregs_t, gpioevent);
3055 else if (regtype == GPIO_REGEVT_INTMSK)
3056 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
3057 else if (regtype == GPIO_REGEVT_INTPOL)
3058 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
3059 else
3060 return 0xffffffff;
3062 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3065 void *
3066 BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event,
3067 bool level, gpio_handler_t cb, void *arg)
3069 si_info_t *sii;
3070 gpioh_item_t *gi;
3072 ASSERT(event);
3073 ASSERT(cb != NULL);
3075 sii = SI_INFO(sih);
3076 if (sih->ccrev < 11)
3077 return NULL;
3079 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
3080 return NULL;
3082 bzero(gi, sizeof(gpioh_item_t));
3083 gi->event = event;
3084 gi->handler = cb;
3085 gi->arg = arg;
3086 gi->level = level;
3088 gi->next = sii->gpioh_head;
3089 sii->gpioh_head = gi;
3091 #ifdef BCMDBG_ERR
3093 gpioh_item_t *h = sii->gpioh_head;
3094 int cnt = 0;
3096 for (; h; h = h->next) {
3097 cnt++;
3098 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3099 h, h->handler, h->event));
3101 SI_ERROR(("gpiohdler total=%d\n", cnt));
3103 #endif
3104 return (void *)(gi);
3107 void
3108 BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh)
3110 si_info_t *sii;
3111 gpioh_item_t *p, *n;
3113 sii = SI_INFO(sih);
3114 if (sih->ccrev < 11)
3115 return;
3117 ASSERT(sii->gpioh_head != NULL);
3118 if ((void*)sii->gpioh_head == gpioh) {
3119 sii->gpioh_head = sii->gpioh_head->next;
3120 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3121 return;
3122 } else {
3123 p = sii->gpioh_head;
3124 n = p->next;
3125 while (n) {
3126 if ((void*)n == gpioh) {
3127 p->next = n->next;
3128 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3129 return;
3131 p = n;
3132 n = n->next;
3136 #ifdef BCMDBG_ERR
3138 gpioh_item_t *h = sii->gpioh_head;
3139 int cnt = 0;
3141 for (; h; h = h->next) {
3142 cnt++;
3143 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3144 h, h->handler, h->event));
3146 SI_ERROR(("gpiohdler total=%d\n", cnt));
3148 #endif
3149 ASSERT(0); /* Not found in list */
3152 void
3153 si_gpio_handler_process(si_t *sih)
3155 si_info_t *sii;
3156 gpioh_item_t *h;
3157 uint32 status;
3158 uint32 level = si_gpioin(sih);
3159 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
3161 sii = SI_INFO(sih);
3162 for (h = sii->gpioh_head; h != NULL; h = h->next) {
3163 if (h->handler) {
3164 status = (h->level ? level : edge);
3166 if (status & h->event)
3167 h->handler(status, h->arg);
3171 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
3174 uint32
3175 si_gpio_int_enable(si_t *sih, bool enable)
3177 si_info_t *sii;
3178 uint offs;
3180 sii = SI_INFO(sih);
3181 if (sih->ccrev < 11)
3182 return 0xffffffff;
3184 offs = OFFSETOF(chipcregs_t, intmask);
3185 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
3189 /* Return the size of the specified SOCRAM bank */
3190 static uint
3191 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type)
3193 uint banksize, bankinfo;
3194 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3196 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
3198 W_REG(sii->osh, &regs->bankidx, bankidx);
3199 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3200 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
3201 return banksize;
3204 void
3205 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
3207 si_info_t *sii;
3208 uint origidx;
3209 uint intr_val = 0;
3210 sbsocramregs_t *regs;
3211 bool wasup;
3212 uint corerev;
3214 sii = SI_INFO(sih);
3216 /* Block ints and save current core */
3217 INTR_OFF(sii, intr_val);
3218 origidx = si_coreidx(sih);
3220 if (!set)
3221 *enable = *protect = 0;
3223 /* Switch to SOCRAM core */
3224 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3225 goto done;
3227 /* Get info for determining size */
3228 if (!(wasup = si_iscoreup(sih)))
3229 si_core_reset(sih, 0, 0);
3231 corerev = si_corerev(sih);
3232 if (corerev >= 10) {
3233 uint32 extcinfo;
3234 uint8 nb;
3235 uint8 i;
3236 uint32 bankidx, bankinfo;
3238 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3239 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3240 for (i = 0; i < nb; i++) {
3241 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3242 W_REG(sii->osh, &regs->bankidx, bankidx);
3243 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3244 if (set) {
3245 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
3246 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
3247 if (*enable) {
3248 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
3249 if (*protect)
3250 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
3252 W_REG(sii->osh, &regs->bankinfo, bankinfo);
3254 else if (i == 0) {
3255 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
3256 *enable = 1;
3257 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
3258 *protect = 1;
3264 /* Return to previous state and core */
3265 if (!wasup)
3266 si_core_disable(sih, 0);
3267 si_setcoreidx(sih, origidx);
3269 done:
3270 INTR_RESTORE(sii, intr_val);
3273 bool
3274 si_socdevram_pkg(si_t *sih)
3276 if (si_socdevram_size(sih) > 0)
3277 return TRUE;
3278 else
3279 return FALSE;
3282 uint32
3283 si_socdevram_size(si_t *sih)
3285 si_info_t *sii;
3286 uint origidx;
3287 uint intr_val = 0;
3288 uint32 memsize = 0;
3289 sbsocramregs_t *regs;
3290 bool wasup;
3291 uint corerev;
3293 sii = SI_INFO(sih);
3295 /* Block ints and save current core */
3296 INTR_OFF(sii, intr_val);
3297 origidx = si_coreidx(sih);
3299 /* Switch to SOCRAM core */
3300 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3301 goto done;
3303 /* Get info for determining size */
3304 if (!(wasup = si_iscoreup(sih)))
3305 si_core_reset(sih, 0, 0);
3307 corerev = si_corerev(sih);
3308 if (corerev >= 10) {
3309 uint32 extcinfo;
3310 uint8 nb;
3311 uint8 i;
3313 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3314 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3315 for (i = 0; i < nb; i++)
3316 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3319 /* Return to previous state and core */
3320 if (!wasup)
3321 si_core_disable(sih, 0);
3322 si_setcoreidx(sih, origidx);
3324 done:
3325 INTR_RESTORE(sii, intr_val);
3327 return memsize;
3330 /* Return the RAM size of the SOCRAM core */
3331 uint32
3332 si_socram_size(si_t *sih)
3334 si_info_t *sii;
3335 uint origidx;
3336 uint intr_val = 0;
3338 sbsocramregs_t *regs;
3339 bool wasup;
3340 uint corerev;
3341 uint32 coreinfo;
3342 uint memsize = 0;
3344 sii = SI_INFO(sih);
3346 /* Block ints and save current core */
3347 INTR_OFF(sii, intr_val);
3348 origidx = si_coreidx(sih);
3350 /* Switch to SOCRAM core */
3351 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3352 goto done;
3354 /* Get info for determining size */
3355 if (!(wasup = si_iscoreup(sih)))
3356 si_core_reset(sih, 0, 0);
3357 corerev = si_corerev(sih);
3358 coreinfo = R_REG(sii->osh, &regs->coreinfo);
3360 /* Calculate size from coreinfo based on rev */
3361 if (corerev == 0)
3362 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
3363 else if (corerev < 3) {
3364 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
3365 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3366 } else if ((corerev <= 7) || (corerev == 12)) {
3367 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3368 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
3369 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
3370 if (lss != 0)
3371 nb --;
3372 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
3373 if (lss != 0)
3374 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
3375 } else {
3376 uint8 i;
3377 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3378 for (i = 0; i < nb; i++)
3379 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
3382 /* Return to previous state and core */
3383 if (!wasup)
3384 si_core_disable(sih, 0);
3385 si_setcoreidx(sih, origidx);
3387 done:
3388 INTR_RESTORE(sii, intr_val);
3390 return memsize;
3393 #ifdef BCMECICOEX
3394 #define NOTIFY_BT_FM_DISABLE(sih, val) \
3395 si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
3396 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
3398 /* Query OTP to see if FM is disabled */
3399 static int
3400 BCMATTACHFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled)
3402 int error = BCME_OK;
3403 uint bitoff = 0;
3404 bool wasup;
3405 void *oh;
3407 /* Determine the bit for the chip */
3408 switch (CHIPID(sih->chip)) {
3409 case BCM4325_CHIP_ID:
3410 if (CHIPREV(sih->chiprev) >= 6)
3411 bitoff = OTP4325_FM_DISABLED_OFFSET;
3412 break;
3413 default:
3414 break;
3417 /* If there is a bit for this chip, check it */
3418 if (bitoff) {
3419 if (!(wasup = si_is_otp_powered(sih))) {
3420 si_otp_power(sih, TRUE);
3423 if ((oh = otp_init(sih)) != NULL)
3424 *FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET);
3425 else
3426 error = BCME_NOTFOUND;
3428 if (!wasup) {
3429 si_otp_power(sih, FALSE);
3433 return error;
3436 bool
3437 si_eci(si_t *sih)
3439 return (!!(sih->cccaps & CC_CAP_ECI));
3442 bool
3443 si_seci(si_t *sih)
3445 return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT);
3448 /* ECI Init routine */
3450 BCMATTACHFN(si_eci_init)(si_t *sih)
3452 uint32 origidx = 0;
3453 si_info_t *sii;
3454 chipcregs_t *cc;
3455 bool fast;
3456 uint16 FMDisabled = FALSE;
3458 /* check for ECI capability */
3459 if (!(sih->cccaps & CC_CAP_ECI))
3460 return BCME_ERROR;
3462 sii = SI_INFO(sih);
3463 fast = SI_FAST(sii);
3464 if (!fast) {
3465 origidx = sii->curidx;
3466 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3467 return BCME_ERROR;
3468 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3469 return BCME_ERROR;
3470 ASSERT(cc);
3472 /* disable level based interrupts */
3473 if (sih->ccrev < 35) {
3474 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0);
3475 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0);
3476 W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0);
3478 else {
3479 W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0);
3480 W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0);
3483 /* Assign eci_output bits between 'wl' and dot11mac */
3484 if (sih->ccrev < 35) {
3485 W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS);
3487 else {
3488 W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS);
3489 W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS);
3492 /* enable only edge based interrupts
3493 * only toggle on bit 62 triggers an interrupt
3495 if (sih->ccrev < 35) {
3496 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0);
3497 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0);
3498 W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0);
3500 else {
3501 W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0);
3502 W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0);
3505 /* restore previous core */
3506 if (!fast)
3507 si_setcoreidx(sih, origidx);
3509 /* if FM disabled in OTP, let BT know */
3510 if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) {
3511 if (FMDisabled) {
3512 NOTIFY_BT_FM_DISABLE(sih, 1);
3516 return 0;
3520 * Write values to BT on eci_output.
3522 void
3523 si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt)
3525 uint32 offset;
3527 /* Nothing to do if there is no eci */
3528 if ((sih->cccaps & CC_CAP_ECI) == 0)
3529 return;
3531 /* Clear interrupt bit by default */
3532 if (interrupt)
3533 si_corereg(sih, SI_CC_IDX, (sih->ccrev < 35 ?
3534 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3535 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3536 (1 << 30), 0);
3538 if (sih->ccrev >= 35) {
3539 if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
3540 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi);
3541 mask = mask & ~0xFFFF0000;
3543 else {
3544 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo);
3545 mask = mask | (1<<30);
3546 val = val & ~(1 << 30);
3549 else {
3550 offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output);
3551 val = val & ~(1 << 30);
3554 si_corereg(sih, SI_CC_IDX, offset, mask, val);
3556 /* Set interrupt bit if needed */
3557 if (interrupt)
3558 si_corereg(sih, SI_CC_IDX,
3559 (sih->ccrev < 35 ?
3560 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3561 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3562 (1 << 30), (1 << 30));
3565 /* seci clock enable/disable */
3566 static void
3567 si_seci_clkreq(si_t *sih, bool enable)
3569 uint32 clk_ctl_st;
3570 uint32 offset;
3571 uint32 val;
3573 if (!si_seci(sih))
3574 return;
3576 if (enable)
3577 val = CLKCTL_STS_SECI_CLK_REQ;
3578 else
3579 val = 0;
3581 offset = OFFSETOF(chipcregs_t, clk_ctl_st);
3583 si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val);
3585 if (!enable)
3586 return;
3588 SPINWAIT((si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL), 100000);
3590 clk_ctl_st = si_corereg(sih, 0, offset, 0, 0);
3591 if (enable) {
3592 if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) {
3593 SI_ERROR(("SECI clock is still not available\n"));
3594 return;
3599 void
3600 BCMINITFN(si_seci_down)(si_t *sih)
3602 uint32 origidx = 0;
3603 si_info_t *sii;
3604 chipcregs_t *cc;
3605 bool fast;
3606 uint32 seci_conf;
3608 if (!si_seci(sih))
3609 return;
3611 sii = SI_INFO(sih);
3612 fast = SI_FAST(sii);
3614 if (!fast) {
3615 origidx = sii->curidx;
3616 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3617 return;
3618 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3619 return;
3620 ASSERT(cc);
3622 /* put seci in reset */
3623 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3624 seci_conf &= ~SECI_ENAB_SECI_ECI;
3625 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3626 seci_conf |= SECI_RESET;
3627 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3629 /* bring down the clock if up */
3630 si_seci_clkreq(sih, FALSE);
3632 /* restore previous core */
3633 if (!fast)
3634 si_setcoreidx(sih, origidx);
3637 /* SECI Init routine, pass in seci_mode */
3638 void *
3639 BCMINITFN(si_seci_init)(si_t *sih, uint8 seci_mode)
3641 uint32 origidx = 0;
3642 uint32 offset;
3643 si_info_t *sii;
3644 void *ptr;
3645 chipcregs_t *cc;
3646 bool fast;
3647 uint32 seci_conf;
3648 uint32 regval;
3650 if (sih->ccrev < 35)
3651 return NULL;
3653 if (!si_seci(sih))
3654 return NULL;
3656 if (seci_mode > SECI_MODE_MASK)
3657 return NULL;
3659 sii = SI_INFO(sih);
3660 fast = SI_FAST(sii);
3661 if (!fast) {
3662 origidx = sii->curidx;
3663 if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3664 return NULL;
3665 } else if ((ptr = CCREGS_FAST(sii)) == NULL)
3666 return NULL;
3667 cc = (chipcregs_t *)ptr;
3668 ASSERT(cc);
3671 /* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
3672 if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
3673 CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3674 regval = R_REG(sii->osh, &cc->chipcontrol);
3675 regval |= 0x2;
3676 W_REG(sii->osh, &cc->chipcontrol, regval);
3678 regval = R_REG(sii->osh, &cc->jtagctrl);
3679 regval |= 0x1;
3680 W_REG(sii->osh, &cc->jtagctrl, regval);
3683 /* enable SECI clock */
3684 si_seci_clkreq(sih, TRUE);
3686 /* put the SECI in reset */
3687 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3688 seci_conf &= ~SECI_ENAB_SECI_ECI;
3689 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3690 seci_conf = SECI_RESET;
3691 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3693 /* set force-low, and set EN_SECI for all non-legacy modes */
3694 seci_conf |= SECI_ENAB_SECIOUT_DIS;
3695 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
3696 (seci_mode == SECI_MODE_HALF_SECI))
3698 seci_conf |= SECI_ENAB_SECI_ECI;
3700 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3702 /* take seci out of reset */
3703 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3704 seci_conf &= ~(SECI_RESET);
3705 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3707 /* set UART/SECI baud rate */
3708 /* hard-coded at 4MBaud for now */
3709 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
3710 (seci_mode == SECI_MODE_HALF_SECI)) {
3711 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
3712 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF); /* 4MBaud */
3713 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
3714 if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
3715 CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3716 /* 43236 ccrev = 36 and MAC clk = 96MHz */
3717 /* 4331 MAC clk = 96MHz */
3718 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
3720 else {
3721 /* 4336 MAC clk is 80MHz */
3722 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22);
3725 /* LCR/MCR settings */
3726 offset = OFFSETOF(chipcregs_t, seci_uart_lcr);
3727 si_corereg(sih, SI_CC_IDX, offset, 0xFF,
3728 (SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */
3729 offset = OFFSETOF(chipcregs_t, seci_uart_mcr);
3730 si_corereg(sih, SI_CC_IDX, offset,
3731 0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */
3733 /* Give control of ECI output regs to MAC core */
3734 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo);
3735 si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS);
3736 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi);
3737 si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS);
3740 /* set the seci mode in seci conf register */
3741 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3742 seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT);
3743 seci_conf |= (seci_mode << SECI_MODE_SHIFT);
3744 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3746 /* Clear force-low bit */
3747 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3748 seci_conf &= ~SECI_ENAB_SECIOUT_DIS;
3749 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3751 /* restore previous core */
3752 if (!fast)
3753 si_setcoreidx(sih, origidx);
3755 return ptr;
3757 #endif /* BCMECICOEX */
3759 void
3760 si_btcgpiowar(si_t *sih)
3762 si_info_t *sii;
3763 uint origidx;
3764 uint intr_val = 0;
3765 chipcregs_t *cc;
3767 sii = SI_INFO(sih);
3769 /* Make sure that there is ChipCommon core present &&
3770 * UART_TX is strapped to 1
3772 if (!(sih->cccaps & CC_CAP_UARTGPIO))
3773 return;
3775 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
3776 INTR_OFF(sii, intr_val);
3778 origidx = si_coreidx(sih);
3780 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3781 ASSERT(cc != NULL);
3783 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
3785 /* restore the original index */
3786 si_setcoreidx(sih, origidx);
3788 INTR_RESTORE(sii, intr_val);
3791 #if !defined(_CFE_) || defined(CFG_WL)
3792 void
3793 si_chipcontrl_epa4331_restore(si_t *sih, uint32 val)
3795 si_info_t *sii;
3796 chipcregs_t *cc;
3797 uint origidx;
3799 sii = SI_INFO(sih);
3800 origidx = si_coreidx(sih);
3801 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3802 W_REG(sii->osh, &cc->chipcontrol, val);
3803 si_setcoreidx(sih, origidx);
3806 uint32
3807 si_chipcontrl_epa4331_read(si_t *sih)
3809 si_info_t *sii;
3810 chipcregs_t *cc;
3811 uint origidx;
3812 uint32 val;
3814 sii = SI_INFO(sih);
3815 origidx = si_coreidx(sih);
3816 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3817 val = R_REG(sii->osh, &cc->chipcontrol);
3818 si_setcoreidx(sih, origidx);
3819 return val;
3822 void
3823 si_chipcontrl_epa4331(si_t *sih, bool on)
3825 si_info_t *sii;
3826 chipcregs_t *cc;
3827 uint origidx;
3828 uint32 val;
3830 sii = SI_INFO(sih);
3831 origidx = si_coreidx(sih);
3833 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3835 val = R_REG(sii->osh, &cc->chipcontrol);
3837 if (on) {
3838 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
3839 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
3840 /* Ext PA Controls for 4331 12x9 Package */
3841 W_REG(sii->osh, &cc->chipcontrol, val);
3842 } else {
3843 /* Ext PA Controls for 4331 12x12 Package */
3844 if (sih->chiprev > 0) {
3845 W_REG(sii->osh, &cc->chipcontrol, val |
3846 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
3847 } else {
3848 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
3851 } else {
3852 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
3853 W_REG(sii->osh, &cc->chipcontrol, val);
3856 si_setcoreidx(sih, origidx);
3859 void
3860 si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
3862 si_info_t *sii;
3863 chipcregs_t *cc;
3864 uint origidx;
3865 uint32 val;
3866 bool sel_chip;
3868 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
3869 (CHIPID(sih->chip) == BCM43431_CHIP_ID);
3870 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
3872 if (!sel_chip)
3873 return;
3875 sii = SI_INFO(sih);
3876 origidx = si_coreidx(sih);
3878 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3880 val = R_REG(sii->osh, &cc->chipcontrol);
3882 if (enter_wowl) {
3883 val |= CCTRL4331_EXTPA_EN;
3884 W_REG(sii->osh, &cc->chipcontrol, val);
3885 } else {
3886 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
3887 W_REG(sii->osh, &cc->chipcontrol, val);
3889 si_setcoreidx(sih, origidx);
3891 #endif /* !_CFE_ || CFG_WL */
3893 uint
3894 si_pll_reset(si_t *sih)
3896 uint err = 0;
3898 uint intr_val = 0;
3899 si_info_t *sii;
3900 sii = SI_INFO(sih);
3901 INTR_OFF(sii, intr_val);
3902 err = si_pll_minresmask_reset(sih, sii->osh);
3903 INTR_RESTORE(sii, intr_val);
3904 return (err);
3907 /* Enable BT-COEX & Ex-PA for 4313 */
3908 void
3909 si_epa_4313war(si_t *sih)
3911 si_info_t *sii;
3912 chipcregs_t *cc;
3913 uint origidx;
3915 sii = SI_INFO(sih);
3916 origidx = si_coreidx(sih);
3918 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3920 /* EPA Fix */
3921 W_REG(sii->osh, &cc->gpiocontrol,
3922 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
3924 si_setcoreidx(sih, origidx);
3927 void
3928 si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
3930 si_info_t *sii;
3931 sii = SI_INFO(sih);
3933 si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear);
3936 /* WL/BT control for 4313 btcombo boards >= P250 */
3937 void
3938 si_btcombo_p250_4313_war(si_t *sih)
3940 si_info_t *sii;
3941 chipcregs_t *cc;
3942 uint origidx;
3944 sii = SI_INFO(sih);
3945 origidx = si_coreidx(sih);
3947 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3948 W_REG(sii->osh, &cc->gpiocontrol,
3949 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
3951 W_REG(sii->osh, &cc->gpioouten,
3952 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
3954 si_setcoreidx(sih, origidx);
3956 void
3957 si_btc_enable_chipcontrol(si_t *sih)
3959 si_info_t *sii;
3960 chipcregs_t *cc;
3961 uint origidx;
3963 sii = SI_INFO(sih);
3964 origidx = si_coreidx(sih);
3966 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3968 /* BT fix */
3969 W_REG(sii->osh, &cc->chipcontrol,
3970 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
3972 si_setcoreidx(sih, origidx);
3974 /* check if the device is removed */
3975 bool
3976 si_deviceremoved(si_t *sih)
3978 uint32 w;
3979 si_info_t *sii;
3981 sii = SI_INFO(sih);
3983 switch (BUSTYPE(sih->bustype)) {
3984 case PCI_BUS:
3985 ASSERT(sii->osh != NULL);
3986 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
3987 if ((w & 0xFFFF) != VENDOR_BROADCOM)
3988 return TRUE;
3989 break;
3991 return FALSE;
3994 bool
3995 si_is_sprom_available(si_t *sih)
3997 if (sih->ccrev >= 31) {
3998 si_info_t *sii;
3999 uint origidx;
4000 chipcregs_t *cc;
4001 uint32 sromctrl;
4003 if ((sih->cccaps & CC_CAP_SROM) == 0)
4004 return FALSE;
4006 sii = SI_INFO(sih);
4007 origidx = sii->curidx;
4008 cc = si_setcoreidx(sih, SI_CC_IDX);
4009 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
4010 si_setcoreidx(sih, origidx);
4011 return (sromctrl & SRC_PRESENT);
4014 switch (CHIPID(sih->chip)) {
4015 case BCM4312_CHIP_ID:
4016 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
4017 case BCM4325_CHIP_ID:
4018 return (sih->chipst & CST4325_SPROM_SEL) != 0;
4019 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4020 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
4021 case BCM43420_CHIP_ID:
4022 case BCM4342_CHIP_ID: {
4023 uint32 spromotp;
4024 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4025 CST4322_SPROM_OTP_SEL_SHIFT;
4026 return (spromotp & CST4322_SPROM_PRESENT) != 0;
4028 case BCM4329_CHIP_ID:
4029 return (sih->chipst & CST4329_SPROM_SEL) != 0;
4030 case BCM4315_CHIP_ID:
4031 return (sih->chipst & CST4315_SPROM_SEL) != 0;
4032 case BCM4319_CHIP_ID:
4033 return (sih->chipst & CST4319_SPROM_SEL) != 0;
4034 case BCM4336_CHIP_ID:
4035 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
4036 case BCM4330_CHIP_ID:
4037 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
4038 case BCM4313_CHIP_ID:
4039 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
4040 case BCM4331_CHIP_ID:
4041 case BCM43431_CHIP_ID:
4042 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
4043 case BCM43131_CHIP_ID:
4044 case BCM43227_CHIP_ID:
4045 case BCM43228_CHIP_ID:
4046 case BCM43428_CHIP_ID:
4047 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
4048 default:
4049 return TRUE;
4053 bool
4054 si_is_otp_disabled(si_t *sih)
4056 switch (CHIPID(sih->chip)) {
4057 case BCM4325_CHIP_ID:
4058 return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN;
4059 case BCM4322_CHIP_ID:
4060 case BCM43221_CHIP_ID:
4061 case BCM43231_CHIP_ID:
4062 case BCM4342_CHIP_ID:
4063 return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4064 CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) !=
4065 CST4322_OTP_PRESENT;
4066 case BCM4329_CHIP_ID:
4067 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN;
4068 case BCM4315_CHIP_ID:
4069 return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN;
4070 case BCM4319_CHIP_ID:
4071 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN;
4072 case BCM4336_CHIP_ID:
4073 return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
4074 case BCM4330_CHIP_ID:
4075 return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
4076 case BCM4313_CHIP_ID:
4077 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
4078 /* These chips always have their OTP on */
4079 case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: case BCM43222_CHIP_ID:
4080 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
4081 case BCM43421_CHIP_ID:
4082 case BCM43226_CHIP_ID:
4083 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4084 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
4085 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
4086 case BCM43131_CHIP_ID:
4087 case BCM43227_CHIP_ID:
4088 case BCM43228_CHIP_ID: case BCM43428_CHIP_ID:
4089 default:
4090 return FALSE;
4094 bool
4095 si_is_otp_powered(si_t *sih)
4097 if (PMUCTL_ENAB(sih))
4098 return si_pmu_is_otp_powered(sih, si_osh(sih));
4099 return TRUE;
4102 void
4103 si_otp_power(si_t *sih, bool on)
4105 if (PMUCTL_ENAB(sih))
4106 si_pmu_otp_power(sih, si_osh(sih), on);
4107 OSL_DELAY(1000);
4110 bool
4111 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4112 si_is_sprom_enabled(si_t *sih)
4113 #else
4114 BCMATTACHFN(si_is_sprom_enabled)(si_t *sih)
4115 #endif
4117 if (PMUCTL_ENAB(sih))
4118 return si_pmu_is_sprom_enabled(sih, si_osh(sih));
4119 return TRUE;
4122 void
4123 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4124 si_sprom_enable(si_t *sih, bool enable)
4125 #else
4126 BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable)
4127 #endif
4129 if (PMUCTL_ENAB(sih))
4130 si_pmu_sprom_enable(sih, si_osh(sih), enable);
4133 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
4135 si_cis_source(si_t *sih)
4137 /* Many chips have the same mapping of their chipstatus field */
4138 static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
4139 static const uint cis_sel_1b[] = { CIS_DEFAULT, CIS_OTP };
4140 UNUSED_PARAMETER(cis_sel_1b);
4142 /* PCI chips use SROM format instead of CIS */
4143 if (BUSTYPE(sih->bustype) == PCI_BUS)
4144 return BCME_NOTFOUND;
4146 switch (CHIPID(sih->chip)) {
4147 case BCM4325_CHIP_ID:
4148 return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4149 CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)];
4150 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4151 case BCM4342_CHIP_ID: {
4152 uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4153 CST4322_SPROM_OTP_SEL_SHIFT;
4154 return ((strap >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[strap]);
4157 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4158 case BCM43234_CHIP_ID: {
4159 uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >>
4160 CST43236_OTP_SEL_SHIFT;
4161 UNUSED_PARAMETER(strap);
4162 return CIS_OTP;
4165 case BCM43237_CHIP_ID: {
4166 uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >>
4167 CST43237_OTP_SEL_SHIFT;
4168 return cis_sel_1b[strap];
4171 case BCM4329_CHIP_ID:
4172 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4173 CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)];
4174 case BCM4315_CHIP_ID:
4175 return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4176 CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)];
4177 case BCM4319_CHIP_ID: {
4178 uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >>
4179 CST4319_SPROM_OTP_SEL_SHIFT);
4180 return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319];
4182 case BCM4336_CHIP_ID: {
4183 if (sih->chipst & CST4336_SPROM_PRESENT)
4184 return CIS_SROM;
4185 if (sih->chipst & CST4336_OTP_PRESENT)
4186 return CIS_OTP;
4187 return CIS_DEFAULT;
4189 case BCM4330_CHIP_ID: {
4190 if (sih->chipst & CST4330_SPROM_PRESENT)
4191 return CIS_SROM;
4192 if (sih->chipst & CST4330_OTP_PRESENT)
4193 return CIS_OTP;
4194 return CIS_DEFAULT;
4196 default:
4197 return CIS_DEFAULT;
4201 /* Read/write to OTP to find the FAB manf */
4203 BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw)
4205 int error = BCME_OK;
4206 uint offset = 0;
4207 uint16 data, mask = 0, shift = 0;
4209 switch (CHIPID(sih->chip)) {
4210 case BCM4329_CHIP_ID:
4211 /* Bit locations 133-130 */
4212 if (sih->chiprev >= 3) {
4213 offset = 8;
4214 mask = 0x3c;
4215 shift = 2;
4217 break;
4218 case BCM5356_CHIP_ID:
4219 /* Bit locations 133-130 */
4220 offset = 8;
4221 mask = 0x3c;
4222 shift = 2;
4223 break;
4224 default:
4225 error = BCME_EPERM;
4226 return error;
4229 if (rw == TRUE) {
4230 /* TRUE --> read */
4231 error = otp_read_word(sih, offset, &data);
4232 if (!error)
4233 *fabid = (data & mask) >> shift;
4234 } else {
4235 data = *fabid;
4236 data = (data << shift) & mask;
4237 #ifdef BCMNVRAMW
4238 error = otp_write_word(sih, offset, data);
4239 #endif /* BCMNVRAMW */
4242 return error;
4245 uint16 BCMINITFN(si_fabid)(si_t *sih)
4247 uint16 fabid = 0;
4248 if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK)
4250 SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));
4253 return fabid;