RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / shared / siutils.c
blobc1f3ddb12334d0f2aedf86b5521eb48d54d37b54
1 /*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2012, 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 350835 2012-08-15 22:17:37Z $
22 #include <bcm_cfg.h>
23 #include <typedefs.h>
24 #include <bcmdefs.h>
25 #include <osl.h>
26 #include <bcmutils.h>
27 #include <siutils.h>
28 #include <bcmdevs.h>
29 #include <hndsoc.h>
30 #include <sbchipc.h>
31 #include <pci_core.h>
32 #include <pcie_core.h>
33 #include <nicpci.h>
34 #include <bcmnvram.h>
35 #include <bcmsrom.h>
36 #include <hndtcam.h>
37 #include <pcicfg.h>
38 #include <sbpcmcia.h>
39 #include <sbsocram.h>
40 #include <bcmotp.h>
41 #include <hndpmu.h>
42 #ifdef BCMSPI
43 #include <spid.h>
44 #endif /* BCMSPI */
45 #if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE)
46 #include <saverestore.h>
47 #endif
49 #include "siutils_priv.h"
51 /* local prototypes */
52 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
53 uint bustype, void *sdh, char **vars, uint *varsz);
54 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
55 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
56 uint *origidx, void *regs);
58 static void si_nvram_process(si_info_t *sii, char *pvars);
59 #if !defined(_CFE_) || defined(CFG_WL)
60 static void si_sromvars_fixup_4331(si_t *sih, char *pvars);
61 #endif /* !_CFE_ || CFG_WL */
63 /* dev path concatenation util */
64 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
65 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
66 static bool si_ispcie(si_info_t *sii);
67 static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype);
69 void si_gci_chipctrl_overrides(osl_t *osh, si_t *sih, char *pvars);
72 /* global variable to indicate reservation/release of gpio's */
73 static uint32 si_gpioreservation = 0;
75 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
77 int do_4360_pcie2_war = 0;
80 * Allocate a si handle.
81 * devid - pci device id (used to determine chip#)
82 * osh - opaque OS handle
83 * regs - virtual address of initial core registers
84 * bustype - pci/pcmcia/sb/sdio/etc
85 * vars - pointer to a pointer area for "environment" variables
86 * varsz - pointer to int to return the size of the vars
88 si_t *
89 BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs,
90 uint bustype, void *sdh, char **vars, uint *varsz)
92 si_info_t *sii;
94 /* alloc si_info_t */
95 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
96 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
97 return (NULL);
100 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
101 MFREE(osh, sii, sizeof(si_info_t));
102 return (NULL);
104 sii->vars = vars ? *vars : NULL;
105 sii->varsz = varsz ? *varsz : 0;
107 return (si_t *)sii;
110 /* global kernel resource */
111 static si_info_t ksii;
113 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
115 /* generic kernel variant of si_attach() */
116 si_t *
117 BCMATTACHFN(si_kattach)(osl_t *osh)
119 static bool ksii_attached = FALSE;
121 if (!ksii_attached) {
122 void *regs;
123 #ifndef SI_ENUM_BASE_VARIABLE
124 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
125 #endif
127 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
128 SI_BUS, NULL,
129 osh != SI_OSH ? &ksii.vars : NULL,
130 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
131 SI_ERROR(("si_kattach: si_doattach failed\n"));
132 REG_UNMAP(regs);
133 return NULL;
135 REG_UNMAP(regs);
137 /* save ticks normalized to ms for si_watchdog_ms() */
138 if (PMUCTL_ENAB(&ksii.pub)) {
139 if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) {
140 /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
141 wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000;
143 else
144 /* based on 32KHz ILP clock */
145 wd_msticks = 32;
146 } else {
147 if (ksii.pub.ccrev < 18)
148 wd_msticks = si_clock(&ksii.pub) / 1000;
149 else
150 wd_msticks = si_alp_clock(&ksii.pub) / 1000;
153 ksii_attached = TRUE;
154 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
155 ksii.pub.ccrev, wd_msticks));
158 return &ksii.pub;
161 bool
162 si_ldo_war(si_t *sih, uint devid)
164 si_info_t *sii = SI_INFO(sih);
165 uint32 w;
166 chipcregs_t *cc;
167 void *regs = sii->curmap;
168 uint32 rev_id, ccst;
170 rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32));
171 rev_id &= 0xff;
172 if (!(((CHIPID(devid) == BCM4322_CHIP_ID) ||
173 (CHIPID(devid) == BCM4342_CHIP_ID) ||
174 (CHIPID(devid) == BCM4322_D11N_ID) ||
175 (CHIPID(devid) == BCM4322_D11N2G_ID) ||
176 (CHIPID(devid) == BCM4322_D11N5G_ID)) &&
177 (rev_id == 0)))
178 return TRUE;
180 SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id));
182 /* switch to chipcommon */
183 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
184 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE);
185 cc = (chipcregs_t *)regs;
187 /* clear bit 7 to fix LDO
188 * write to register *blindly* WITHOUT read since read may timeout
189 * because the default clock is 32k ILP
191 W_REG(sii->osh, &cc->regcontrol_addr, 0);
192 /* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
193 W_REG(sii->osh, &cc->regcontrol_data, 0x3001);
195 OSL_DELAY(5000);
197 /* request ALP_AVAIL through PMU to move sb out of ILP */
198 W_REG(sii->osh, &cc->min_res_mask, 0x0d);
200 SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL)
201 == 0, PMU_MAX_TRANSITION_DLY);
203 if ((ccst & CCS_ALPAVAIL) == 0) {
204 SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst));
205 return FALSE;
207 SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
209 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w);
211 return TRUE;
214 static bool
215 BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh)
217 /* need to set memseg flag for CF card first before any sb registers access */
218 if (BUSTYPE(bustype) == PCMCIA_BUS)
219 sii->memseg = TRUE;
221 if (BUSTYPE(bustype) == PCI_BUS) {
222 if (!si_ldo_war((si_t *)sii, devid))
223 return FALSE;
226 /* kludge to enable the clock on the 4306 which lacks a slowclock */
227 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
228 si_clkctl_xtal(&sii->pub, XTAL|PLL, ON);
231 return TRUE;
234 static bool
235 BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
236 uint *origidx, void *regs)
238 bool pci, pcie, pcie_gen2 = FALSE;
239 uint i;
240 uint pciidx, pcieidx, pcirev, pcierev;
242 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
243 ASSERT((uintptr)cc);
245 /* get chipcommon rev */
246 sii->pub.ccrev = (int)si_corerev(&sii->pub);
248 /* get chipcommon chipstatus */
249 if (sii->pub.ccrev >= 11)
250 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
252 /* get chipcommon capabilites */
253 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
254 /* get chipcommon extended capabilities */
256 if (sii->pub.ccrev >= 35)
257 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
259 /* get pmu rev and caps */
260 if (sii->pub.cccaps & CC_CAP_PMU) {
261 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
262 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
265 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
266 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
267 sii->pub.pmucaps));
269 /* figure out bus/orignal core idx */
270 sii->pub.buscoretype = NODEV_CORE_ID;
271 sii->pub.buscorerev = (uint)NOREV;
272 sii->pub.buscoreidx = BADIDX;
274 pci = pcie = FALSE;
275 pcirev = pcierev = (uint)NOREV;
276 pciidx = pcieidx = BADIDX;
278 for (i = 0; i < sii->numcores; i++) {
279 uint cid, crev;
281 si_setcoreidx(&sii->pub, i);
282 cid = si_coreid(&sii->pub);
283 crev = si_corerev(&sii->pub);
285 /* Display cores found */
286 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
287 i, cid, crev, sii->coresba[i], sii->regs[i]));
289 if (BUSTYPE(bustype) == PCI_BUS) {
290 if (cid == PCI_CORE_ID) {
291 pciidx = i;
292 pcirev = crev;
293 pci = TRUE;
294 } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
295 pcieidx = i;
296 pcierev = crev;
297 pcie = TRUE;
298 if (cid == PCIE2_CORE_ID)
299 pcie_gen2 = TRUE;
301 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
302 (cid == PCMCIA_CORE_ID)) {
303 sii->pub.buscorerev = crev;
304 sii->pub.buscoretype = cid;
305 sii->pub.buscoreidx = i;
308 /* find the core idx before entering this func. */
309 if ((savewin && (savewin == sii->coresba[i])) ||
310 (regs == sii->regs[i]))
311 *origidx = i;
314 if (pci && pcie) {
315 if (si_ispcie(sii))
316 pci = FALSE;
317 else
318 pcie = FALSE;
320 if (pci) {
321 sii->pub.buscoretype = PCI_CORE_ID;
322 sii->pub.buscorerev = pcirev;
323 sii->pub.buscoreidx = pciidx;
324 } else if (pcie) {
325 if (pcie_gen2)
326 sii->pub.buscoretype = PCIE2_CORE_ID;
327 else
328 sii->pub.buscoretype = PCIE_CORE_ID;
329 sii->pub.buscorerev = pcierev;
330 sii->pub.buscoreidx = pcieidx;
333 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
334 sii->pub.buscorerev));
336 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
337 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
338 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
340 /* fixup necessary chip/core configurations */
341 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
342 if (SI_FAST(sii)) {
343 if (!sii->pch &&
344 ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh,
345 (void *)PCIEREGS(sii))) == NULL))
346 return FALSE;
348 if (si_pci_fixcfg(&sii->pub)) {
349 SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
350 return FALSE;
355 /* return to the original core */
356 si_setcoreidx(&sii->pub, *origidx);
358 return TRUE;
361 static uint32
362 si_fixup_vid(si_info_t *sii, char *pvars, uint32 conf_vid)
364 struct si_pub *sih = &sii->pub;
365 uint32 srom_vid;
367 if (BUSTYPE(sih->bustype) != PCI_BUS)
368 return conf_vid;
370 if ((CHIPID(sih->chip) != BCM4331_CHIP_ID) && (CHIPID(sih->chip) != BCM43431_CHIP_ID))
371 return conf_vid;
373 /* Ext PA Controls for 4331 12x9 Package */
374 if (sih->chippkg != 9)
375 return conf_vid;
377 srom_vid = (getintvar(pvars, "boardtype") << 16) | getintvar(pvars, "subvid");
378 if (srom_vid != conf_vid) {
379 SI_ERROR(("%s: Override mismatch conf_vid(0x%04x) with srom_vid(0x%04x)\n",
380 __FUNCTION__, conf_vid, srom_vid));
381 conf_vid = srom_vid;
384 return conf_vid;
387 static void
388 BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars)
390 uint w = 0;
391 if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
392 w = getintvar(pvars, "regwindowsz");
393 sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
396 /* get boardtype and boardrev */
397 switch (BUSTYPE(sii->pub.bustype)) {
398 case PCI_BUS:
399 /* do a pci config read to get subsystem id and subvendor id */
400 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
401 w = si_fixup_vid(sii, pvars, w);
403 /* Let nvram variables override subsystem Vend/ID */
404 if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor"))
405 == 0) {
406 #ifdef BCMHOSTVARS
407 if ((w & 0xffff) == 0)
408 sii->pub.boardvendor = VENDOR_BROADCOM;
409 else
410 #endif /* !BCMHOSTVARS */
411 sii->pub.boardvendor = w & 0xffff;
413 else
414 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
415 sii->pub.boardvendor, w & 0xffff));
416 if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype"))
417 == 0) {
418 if ((sii->pub.boardtype = getintvar(pvars, "boardtype")) == 0)
419 sii->pub.boardtype = (w >> 16) & 0xffff;
421 else
422 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
423 sii->pub.boardtype, (w >> 16) & 0xffff));
424 break;
426 case PCMCIA_BUS:
427 sii->pub.boardvendor = getintvar(pvars, "manfid");
428 sii->pub.boardtype = getintvar(pvars, "prodid");
429 break;
432 case SI_BUS:
433 case JTAG_BUS:
434 sii->pub.boardvendor = VENDOR_BROADCOM;
435 if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
436 if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0)
437 sii->pub.boardtype = 0xffff;
439 if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
440 /* do a pci config read to get subsystem id and subvendor id */
441 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
442 sii->pub.boardvendor = w & 0xffff;
443 sii->pub.boardtype = (w >> 16) & 0xffff;
445 break;
448 if (sii->pub.boardtype == 0) {
449 SI_ERROR(("si_doattach: unknown board type\n"));
450 ASSERT(sii->pub.boardtype);
453 sii->pub.boardrev = getintvar(pvars, "boardrev");
454 sii->pub.boardflags = getintvar(pvars, "boardflags");
457 #if !defined(_CFE_) || defined(CFG_WL)
458 static void
459 BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars)
462 const char *sromvars[] =
463 {"extpagain2g", "extpagain5g"};
464 int sromvars_size = sizeof(sromvars)/sizeof(char *);
465 int ii;
466 uint boardtype = sih->boardtype;
467 uint boardrev = sih->boardrev;
468 bool update = ((boardtype == BCM94331BU_SSID) ||
469 (boardtype == BCM94331S9BU_SSID) ||
470 (boardtype == BCM94331MCI_SSID) ||
471 (boardtype == BCM94331MC_SSID) ||
472 (boardtype == BCM94331PCIEBT4_SSID) ||
473 (boardtype == BCM94331X19 && boardrev == 0x1100) ||
474 (boardtype == BCM94331HM_SSID && boardrev < 0x1152));
476 if (pvars == NULL || !update) {
477 return;
480 for (ii = 0; ii < sromvars_size; ii++) {
481 char* val = getvar(pvars, sromvars[ii]);
483 while (val && *val) {
484 *val = '0';
485 val++;
489 #endif /* !_CFE_ || CFG_WL */
491 #if defined(CONFIG_XIP) && defined(BCMTCAM)
492 extern uint8 patch_pair;
493 #endif /* CONFIG_XIP && BCMTCAM */
495 typedef struct {
496 uint8 uart_tx;
497 uint32 uart_rx;
498 } si_mux4335_uartopt_t;
500 /* note: each index corr to MUXENAB4335_UART mask - 1 */
501 static const si_mux4335_uartopt_t BCMATTACHDATA(mux4335_uartopt)[] = {
502 {CC4335_PIN_GPIO_06, CC4335_PIN_GPIO_02},
503 {CC4335_PIN_GPIO_12, CC4335_PIN_GPIO_13},
504 {CC4335_PIN_SDIO_DATA0, CC4335_PIN_SDIO_CMD},
505 {CC4335_PIN_RF_SW_CTRL_9, CC4335_PIN_RF_SW_CTRL_8}
508 /* want to have this available all the time to switch mux for debugging */
509 void
510 BCMATTACHFN(si_muxenab)(si_t *sih, uint32 w)
512 uint32 chipcontrol, pmu_chipcontrol;
514 pmu_chipcontrol = si_pmu_chipcontrol(sih, 1, 0, 0);
515 chipcontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
516 0, 0);
518 switch (CHIPID(sih->chip)) {
519 case BCM4330_CHIP_ID:
520 /* clear the bits */
521 chipcontrol &= ~(CCTRL_4330_JTAG_DISABLE | CCTRL_4330_ERCX_SEL |
522 CCTRL_4330_GPIO_SEL | CCTRL_4330_SDIO_HOST_WAKE);
523 pmu_chipcontrol &= ~PCTL_4330_SERIAL_ENAB;
525 /* 4330 default is to have jtag enabled */
526 if (!(w & MUXENAB_JTAG))
527 chipcontrol |= CCTRL_4330_JTAG_DISABLE;
528 if (w & MUXENAB_UART)
529 pmu_chipcontrol |= PCTL_4330_SERIAL_ENAB;
530 if (w & MUXENAB_GPIO)
531 chipcontrol |= CCTRL_4330_GPIO_SEL;
532 if (w & MUXENAB_ERCX)
533 chipcontrol |= CCTRL_4330_ERCX_SEL;
534 if (w & MUXENAB_HOST_WAKE)
535 chipcontrol |= CCTRL_4330_SDIO_HOST_WAKE;
536 break;
537 case BCM4336_CHIP_ID:
538 if (w & MUXENAB_UART)
539 pmu_chipcontrol |= PCTL_4336_SERIAL_ENAB;
540 else
541 pmu_chipcontrol &= ~PCTL_4336_SERIAL_ENAB;
542 break;
543 case BCM4360_CHIP_ID:
544 case BCM43460_CHIP_ID:
545 case BCM4352_CHIP_ID:
546 if (w & MUXENAB_UART)
547 chipcontrol |= CCTL_4360_UART_SEL;
548 break;
549 case BCM43143_CHIP_ID:
550 chipcontrol = 0;
551 /* 43143 does not support ERCX */
552 if (!(w & MUXENAB_UART))
553 chipcontrol |= CCTRL_43143_RF_XSWCTRL;
554 /* JTAG is enabled when SECI is disabled */
555 if (w & MUXENAB_SECI)
556 chipcontrol |= CCTRL_43143_SECI;
557 if (w & MUXENAB_BT_LEGACY)
558 chipcontrol |= CCTRL_43143_BT_LEGACY;
559 if (w & MUXENAB_I2S_EN)
560 chipcontrol |= CCTRL_43143_I2S_MODE;
561 if (w & MUXENAB_I2S_MASTER)
562 chipcontrol |= CCTRL_43143_I2S_MASTER;
563 if (w & MUXENAB_I2S_FULL)
564 chipcontrol |= CCTRL_43143_I2S_FULL;
565 if (!(w & MUXENAB_SFLASH))
566 chipcontrol |= CCTRL_43143_GSIO;
567 if (w & MUXENAB_RFSWCTRL0)
568 chipcontrol |= CCTRL_43143_RF_SWCTRL_0;
569 if (w & MUXENAB_RFSWCTRL1)
570 chipcontrol |= CCTRL_43143_RF_SWCTRL_1;
571 if (w & MUXENAB_RFSWCTRL2)
572 chipcontrol |= CCTRL_43143_RF_SWCTRL_2;
573 if (w & MUXENAB_HOST_WAKE)
574 chipcontrol |= CCTRL_43143_HOST_WAKE0;
575 if (w & MUXENAB_HOST_WAKE1)
576 chipcontrol |= CCTRL_43143_HOST_WAKE1;
577 break;
578 case BCM43242_CHIP_ID:
579 case BCM43243_CHIP_ID:
580 /* clear the bits */
581 pmu_chipcontrol &= ~CCTRL1_4324_GPIO_SEL;
582 if (w & MUXENAB_GPIO)
583 pmu_chipcontrol |= CCTRL1_4324_GPIO_SEL;
584 break;
586 case BCM4335_CHIP_ID:
587 /* drive default pins for UART. Note: 15 values possible;
588 * 0 means disabled; 1 means index to 0 in mux4335_uartopt
589 * array, etc.
591 if (w & MUXENAB4335_UART_MASK) {
592 uint32 uart_rx = 0, uart_tx = 0;
593 uint8 uartopt_ix = (w & MUXENAB4335_UART_MASK) - 1;
595 uart_rx = mux4335_uartopt[uartopt_ix].uart_rx;
596 uart_tx = mux4335_uartopt[uartopt_ix].uart_tx;
598 si_gci_set_functionsel(sih, uart_rx, CC4335_FNSEL_UART);
599 si_gci_set_functionsel(sih, uart_tx, CC4335_FNSEL_UART);
601 break;
603 default:
604 /* muxenab specified for an unsupported chip */
605 ASSERT(0);
606 break;
609 /* write both updated values to hw */
610 si_pmu_chipcontrol(sih, 1, ~0, pmu_chipcontrol);
611 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
612 ~0, chipcontrol);
615 /* write 'val' to the gci chip control register indexed by 'reg' */
616 uint32
617 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
619 /* because NFLASH and GCI clashes in 0xC00 */
620 #ifndef NFLASH_SUPPORT
621 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_indirect_addr), ~0, reg);
622 return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_chipctrl), mask, val);
623 #else /* NFLASH_SUPPORT */
624 ASSERT(0);
625 return 0xFFFFFFFF;
626 #endif
629 /* input: pin number
630 * output: chipcontrol reg and bits to shift for pin fn-sel's first regbit.
631 * eg: gpio9 will give regidx: 1 and pos 4
633 uint8
634 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos)
636 *regidx = (pin / 8);
637 *pos = (pin % 8)*4;
639 SI_MSG(("si_gci_get_chipctrlreg_idx:%d:%d:%d\n", pin, *regidx, *pos));
641 return 0;
644 /* setup a given pin for fnsel function */
645 void
646 si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel)
648 uint32 reg = 0, pos = 0;
650 SI_MSG(("si_gci_set_functionsel:%d\n", pin));
652 si_gci_get_chipctrlreg_idx(pin, &reg, &pos);
653 si_gci_chipcontrol(sih, reg, GCIMASK(pos), GCIPOSVAL(fnsel, pos));
656 void
657 si_gci_chipctrl_overrides(osl_t *osh, si_t *sih, char *pvars)
659 uint8 num_cc = 0;
660 char gciccstr[16];
661 const char *otp_val;
662 uint32 gciccval = 0, cap1 = 0;
663 int i = 0;
665 /* because NFLASH and GCI clashes in 0xC00 */
666 #ifndef NFLASH_SUPPORT
667 cap1 = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_corecaps1), 0, 0);
668 #else /* NFLASH_SUPPORT */
669 ASSERT(0);
670 #endif
671 num_cc = CC_GCI_NUMCHIPCTRLREGS(cap1);
673 for (i = 0; i < num_cc; i++) {
674 snprintf(gciccstr, sizeof(gciccstr), "gcr%d", i);
676 if ((otp_val = getvar(NULL, gciccstr)) == NULL)
677 continue;
679 gciccval = (uint32) getintvar(pvars, gciccstr);
680 si_gci_chipcontrol(sih, i, ~0, gciccval);
684 static si_info_t *
685 BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs,
686 uint bustype, void *sdh, char **vars, uint *varsz)
688 struct si_pub *sih = &sii->pub;
689 uint32 w, savewin;
690 chipcregs_t *cc;
691 char *pvars = NULL;
692 uint origidx;
693 #if !defined(_CFE_) || defined(CFG_WL)
694 bool fixup_boardtype = FALSE;
695 #endif /* !defined(_CFE_) || defined(CFG_WL) */
696 ASSERT(GOODREGS(regs));
698 bzero((uchar*)sii, sizeof(si_info_t));
700 savewin = 0;
702 sih->buscoreidx = BADIDX;
704 sii->curmap = regs;
705 sii->sdh = sdh;
706 sii->osh = osh;
708 #ifdef SI_ENUM_BASE_VARIABLE
709 si_enum_base_init(sih, bustype);
710 #endif /* SI_ENUM_BASE_VARIABLE */
712 /* check to see if we are a si core mimic'ing a pci core */
713 if ((bustype == PCI_BUS) &&
714 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
715 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
716 "devid:0x%x\n", __FUNCTION__, devid));
717 bustype = SI_BUS;
720 /* find Chipcommon address */
721 if (bustype == PCI_BUS) {
722 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
723 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
724 savewin = SI_ENUM_BASE;
725 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
726 cc = (chipcregs_t *)regs;
727 } else {
728 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
731 sih->bustype = bustype;
732 if (bustype != BUSTYPE(bustype)) {
733 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
734 bustype, BUSTYPE(bustype)));
735 return NULL;
738 /* bus/core/clk setup for register access */
739 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
740 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
741 return NULL;
744 /* ChipID recognition.
745 * We assume we can read chipid at offset 0 from the regs arg.
746 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
747 * some way of recognizing them needs to be added here.
749 if (!cc) {
750 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
751 return NULL;
753 w = R_REG(osh, &cc->chipid);
754 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
755 /* Might as wll fill in chip id rev & pkg */
756 sih->chip = w & CID_ID_MASK;
757 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
758 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
760 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
761 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
762 sih->chippkg = BCM4329_182PIN_PKG_ID;
764 sih->issim = IS_SIM(sih->chippkg);
766 /* scan for cores */
767 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
768 SI_MSG(("Found chip type SB (0x%08x)\n", w));
769 sb_scan(&sii->pub, regs, devid);
770 } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
771 (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) {
772 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
773 SI_MSG(("Found chip type AI (0x%08x)\n", w));
774 else
775 SI_MSG(("Found chip type NAI (0x%08x)\n", w));
776 /* pass chipc address instead of original core base */
777 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
778 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
779 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
780 /* pass chipc address instead of original core base */
781 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
782 } else {
783 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
784 return NULL;
786 /* no cores found, bail out */
787 if (sii->numcores == 0) {
788 SI_ERROR(("si_doattach: could not find any cores\n"));
789 return NULL;
791 /* bus/core/clk setup */
792 origidx = SI_CC_IDX;
793 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
794 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
795 goto exit;
798 #if !defined(_CFE_) || defined(CFG_WL)
799 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
800 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
801 CST4322_SPROM_PRESENT))) {
802 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
803 return NULL;
806 /* assume current core is CC */
807 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
808 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
809 CHIPID(sih->chip) == BCM43234_CHIP_ID ||
810 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
811 (CHIPREV(sii->pub.chiprev) <= 2))) {
813 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
814 uint clkdiv;
815 clkdiv = R_REG(osh, &cc->clkdiv);
816 /* otp_clk_div is even number, 120/14 < 9mhz */
817 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
818 W_REG(osh, &cc->clkdiv, clkdiv);
819 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
821 OSL_DELAY(10);
824 if (bustype == PCI_BUS) {
825 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
826 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
827 /* Check Ext PA Controls for 4331 12x9 Package before the fixup */
828 if (sih->chippkg == 9) {
829 uint32 val = si_chipcontrl_read(sih);
830 fixup_boardtype = ((val & CCTRL4331_EXTPA_ON_GPIO2_5) ==
831 CCTRL4331_EXTPA_ON_GPIO2_5);
833 /* set default mux pin to SROM */
834 si_chipcontrl_epa4331(sih, FALSE);
835 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100);
836 OSL_DELAY(20000); /* Srom read takes ~12mS */
839 if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
840 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
841 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
842 (CHIPREV(sih->chiprev) <= 2)) {
843 pcie_disable_TL_clk_gating(sii->pch);
844 pcie_set_L1_entry_time(sii->pch, 0x40);
847 #ifdef BCMQT
848 /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
849 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
850 * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words.
853 uint otpclkdiv = 0;
855 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
856 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
857 otpclkdiv = 2;
858 } else if ((CHIPID(sih->chip) == BCM43131_CHIP_ID) ||
859 (CHIPID(sih->chip) == BCM43217_CHIP_ID) ||
860 (CHIPID(sih->chip) == BCM43227_CHIP_ID) ||
861 (CHIPID(sih->chip) == BCM43228_CHIP_ID)) {
862 otpclkdiv = 4;
865 if (otpclkdiv != 0) {
866 uint clkdiv, savecore;
867 savecore = si_coreidx(sih);
868 si_setcore(sih, CC_CORE_ID, 0);
870 clkdiv = R_REG(osh, &cc->clkdiv);
871 clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT);
872 W_REG(osh, &cc->clkdiv, clkdiv);
874 SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv));
875 si_setcoreidx(sih, savecore);
878 #endif /* BCMQT */
880 #endif /* !_CFE_ || CFG_WL */
881 #ifdef SI_SPROM_PROBE
882 si_sprom_init(sih);
883 #endif /* SI_SPROM_PROBE */
885 #if !defined(BCMHIGHSDIO)
886 /* Init nvram from flash if it exists */
887 nvram_init((void *)&(sii->pub));
889 /* Init nvram from sprom/otp if they exist */
890 if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
891 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
892 goto exit;
894 pvars = vars ? *vars : NULL;
896 si_nvram_process(sii, pvars);
898 #if !defined(_CFE_) || defined(CFG_WL)
899 if (bustype == PCI_BUS) {
900 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
901 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
902 si_sromvars_fixup_4331(sih, pvars);
903 if (fixup_boardtype)
904 sii->pub.boardtype = getintvar(pvars, "boardtype");
907 #endif /* !_CFE_ || CFG_WL */
909 /* === NVRAM, clock is ready === */
910 #else
911 pvars = NULL;
912 BCM_REFERENCE(pvars);
913 #endif
916 #if defined(CONFIG_XIP) && defined(BCMTCAM)
917 /* patch the ROM if there are any patch pairs from OTP/SPROM */
918 if (patch_pair) {
920 #if defined(__ARM_ARCH_7R__)
921 hnd_tcam_bootloader_load(si_setcore(sih, ARMCR4_CORE_ID, 0), pvars);
922 #else
923 hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars);
924 #endif
925 si_setcoreidx(sih, origidx);
927 #endif /* CONFIG_XIP && BCMTCAM */
929 /* bootloader should retain default pulls */
930 #ifndef BCM_BOOTLOADER
931 if (sii->pub.ccrev >= 20) {
932 uint32 gpiopullup = 0, gpiopulldown = 0;
933 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
934 ASSERT(cc != NULL);
936 /* 4314/43142 has pin muxing, don't clear gpio bits */
937 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
938 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
939 gpiopullup |= 0x402e0;
940 gpiopulldown |= 0x20500;
943 W_REG(osh, &cc->gpiopullup, gpiopullup);
944 W_REG(osh, &cc->gpiopulldown, gpiopulldown);
945 si_setcoreidx(sih, origidx);
947 #endif /* !BCM_BOOTLOADER */
949 /* PMU specific initializations */
950 if (PMUCTL_ENAB(sih)) {
951 uint32 xtalfreq;
952 si_pmu_init(sih, sii->osh);
953 si_pmu_chip_init(sih, sii->osh);
954 xtalfreq = getintvar(pvars, "xtalfreq");
955 switch (CHIPID(sih->chip)) {
956 case BCM43242_CHIP_ID:
957 case BCM43243_CHIP_ID:
958 xtalfreq = 37400;
959 break;
960 case BCM43143_CHIP_ID:
961 xtalfreq = 20000;
962 break;
963 default:
964 break;
966 /* If xtalfreq var not available, try to measure it */
967 if (xtalfreq == 0)
968 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
969 #if !defined(BCMHIGHSDIO)
970 si_pmu_pll_init(sih, sii->osh, xtalfreq);
971 si_pmu_res_init(sih, sii->osh);
972 #endif
973 si_pmu_swreg_init(sih, sii->osh);
976 /* setup the GPIO based LED powersave register */
977 if (sii->pub.ccrev >= 16) {
978 if ((w = getintvar(pvars, "leddc")) == 0)
979 w = DEFAULT_GPIOTIMERVAL;
980 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
983 if (PCI_FORCEHT(sii)) {
984 SI_MSG(("si_doattach: force HT\n"));
985 sih->pci_pr32414 = TRUE;
986 si_clkctl_init(sih);
987 _si_clkctl_cc(sii, CLK_FAST);
990 #if !defined(_CFE_) || defined(CFG_WL)
991 if (PCIE(sii)) {
992 ASSERT(sii->pch != NULL);
994 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
996 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
997 (CHIPID(sih->chip) == BCM4312_CHIP_ID)) {
998 SI_MSG(("si_doattach: clear initiator timeout\n"));
999 sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0));
1003 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
1004 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
1005 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
1006 if (CHIPREV(sih->chiprev) == 0) {
1007 SI_MSG(("Applying 43224A0 WARs\n"));
1008 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
1009 CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE);
1010 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
1011 CCTRL_43224A0_12MA_LED_DRIVE);
1013 if (CHIPREV(sih->chiprev) >= 1) {
1014 SI_MSG(("Applying 43224B0+ WARs\n"));
1015 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
1016 CCTRL_43224B0_12MA_LED_DRIVE);
1020 /* configure default pinmux enables for the chip */
1021 if (getvar(pvars, "muxenab") != NULL) {
1022 w = getintvar(pvars, "muxenab");
1023 si_muxenab((si_t *)sii, w);
1026 /* enable GPIO interrupts when clocks are off */
1027 if (sii->pub.ccrev >= 21) {
1028 uint32 corecontrol;
1029 corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
1030 0, 0);
1031 corecontrol |= CC_ASYNCGPIO;
1032 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
1033 corecontrol, corecontrol);
1036 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
1037 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
1038 SI_MSG(("Applying 4313 WARs\n"));
1039 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, CCTRL_4313_12MA_LED_DRIVE);
1041 #endif /* !_CFE_ || CFG_WL */
1043 #if defined(SAVERESTORE)
1044 sr_save_restore_init(sih);
1045 #endif
1046 /* clear any previous epidiag-induced target abort */
1047 ASSERT(!si_taclear(sih, FALSE));
1049 if ((CHIPID(sih->chip) == BCM4335_CHIP_ID) ||
1050 0) {
1051 si_gci_chipctrl_overrides(osh, sih, pvars);
1054 return (sii);
1056 exit:
1057 if (BUSTYPE(sih->bustype) == PCI_BUS) {
1058 if (sii->pch)
1059 pcicore_deinit(sii->pch);
1060 sii->pch = NULL;
1063 return NULL;
1066 /* may be called with core in reset */
1067 void
1068 BCMATTACHFN(si_detach)(si_t *sih)
1070 si_info_t *sii;
1071 uint idx;
1073 #if defined(STA)
1074 struct si_pub *si_local = NULL;
1075 bcopy(&sih, &si_local, sizeof(si_t*));
1076 #endif
1078 sii = SI_INFO(sih);
1080 if (sii == NULL)
1081 return;
1083 if (BUSTYPE(sih->bustype) == SI_BUS)
1084 for (idx = 0; idx < SI_MAXCORES; idx++)
1085 if (sii->regs[idx]) {
1086 REG_UNMAP(sii->regs[idx]);
1087 sii->regs[idx] = NULL;
1090 #if defined(STA)
1091 #if !defined(BCMHIGHSDIO)
1092 srom_var_deinit((void *)si_local);
1093 #endif
1094 nvram_exit((void *)si_local); /* free up nvram buffers */
1095 #endif
1097 if (BUSTYPE(sih->bustype) == PCI_BUS) {
1098 if (sii->pch)
1099 pcicore_deinit(sii->pch);
1100 sii->pch = NULL;
1103 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
1104 if (sii != &ksii)
1105 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
1106 MFREE(sii->osh, sii, sizeof(si_info_t));
1109 void *
1110 si_osh(si_t *sih)
1112 si_info_t *sii;
1114 sii = SI_INFO(sih);
1115 return sii->osh;
1118 void
1119 si_setosh(si_t *sih, osl_t *osh)
1121 si_info_t *sii;
1123 sii = SI_INFO(sih);
1124 if (sii->osh != NULL) {
1125 SI_ERROR(("osh is already set....\n"));
1126 ASSERT(!sii->osh);
1128 sii->osh = osh;
1131 /* register driver interrupt disabling and restoring callback functions */
1132 void
1133 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
1134 void *intrsenabled_fn, void *intr_arg)
1136 si_info_t *sii;
1138 sii = SI_INFO(sih);
1139 sii->intr_arg = intr_arg;
1140 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
1141 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
1142 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
1143 /* save current core id. when this function called, the current core
1144 * must be the core which provides driver functions(il, et, wl, etc.)
1146 sii->dev_coreid = sii->coreid[sii->curidx];
1149 void
1150 si_deregister_intr_callback(si_t *sih)
1152 si_info_t *sii;
1154 sii = SI_INFO(sih);
1155 sii->intrsoff_fn = NULL;
1158 uint
1159 si_intflag(si_t *sih)
1161 si_info_t *sii = SI_INFO(sih);
1163 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1164 return sb_intflag(sih);
1165 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1166 return R_REG(sii->osh, ((uint32 *)(uintptr)
1167 (sii->oob_router + OOB_STATUSA)));
1168 else {
1169 ASSERT(0);
1170 return 0;
1174 uint
1175 si_flag(si_t *sih)
1177 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1178 return sb_flag(sih);
1179 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1180 return ai_flag(sih);
1181 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1182 return ub_flag(sih);
1183 else {
1184 ASSERT(0);
1185 return 0;
1189 void
1190 si_setint(si_t *sih, int siflag)
1192 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1193 sb_setint(sih, siflag);
1194 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1195 ai_setint(sih, siflag);
1196 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1197 ub_setint(sih, siflag);
1198 else
1199 ASSERT(0);
1202 uint
1203 si_coreid(si_t *sih)
1205 si_info_t *sii;
1207 sii = SI_INFO(sih);
1208 return sii->coreid[sii->curidx];
1211 uint
1212 si_coreidx(si_t *sih)
1214 si_info_t *sii;
1216 sii = SI_INFO(sih);
1217 return sii->curidx;
1220 /* return the core-type instantiation # of the current core */
1221 uint
1222 si_coreunit(si_t *sih)
1224 si_info_t *sii;
1225 uint idx;
1226 uint coreid;
1227 uint coreunit;
1228 uint i;
1230 sii = SI_INFO(sih);
1231 coreunit = 0;
1233 idx = sii->curidx;
1235 ASSERT(GOODREGS(sii->curmap));
1236 coreid = si_coreid(sih);
1238 /* count the cores of our type */
1239 for (i = 0; i < idx; i++)
1240 if (sii->coreid[i] == coreid)
1241 coreunit++;
1243 return (coreunit);
1246 uint
1247 si_corevendor(si_t *sih)
1249 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1250 return sb_corevendor(sih);
1251 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1252 return ai_corevendor(sih);
1253 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1254 return ub_corevendor(sih);
1255 else {
1256 ASSERT(0);
1257 return 0;
1261 bool
1262 si_backplane64(si_t *sih)
1264 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
1267 uint
1268 si_corerev(si_t *sih)
1270 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1271 return sb_corerev(sih);
1272 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1273 return ai_corerev(sih);
1274 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1275 return ub_corerev(sih);
1276 else {
1277 ASSERT(0);
1278 return 0;
1282 /* return index of coreid or BADIDX if not found */
1283 uint
1284 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
1286 si_info_t *sii;
1287 uint found;
1288 uint i;
1290 sii = SI_INFO(sih);
1292 found = 0;
1294 for (i = 0; i < sii->numcores; i++)
1295 if (sii->coreid[i] == coreid) {
1296 if (found == coreunit)
1297 return (i);
1298 found++;
1301 return (BADIDX);
1304 /* return list of found cores */
1305 uint
1306 si_corelist(si_t *sih, uint coreid[])
1308 si_info_t *sii;
1310 sii = SI_INFO(sih);
1312 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
1313 return (sii->numcores);
1316 /* return current register mapping */
1317 void *
1318 si_coreregs(si_t *sih)
1320 si_info_t *sii;
1322 sii = SI_INFO(sih);
1323 ASSERT(GOODREGS(sii->curmap));
1325 return (sii->curmap);
1329 * This function changes logical "focus" to the indicated core;
1330 * must be called with interrupts off.
1331 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1333 void *
1334 si_setcore(si_t *sih, uint coreid, uint coreunit)
1336 uint idx;
1338 idx = si_findcoreidx(sih, coreid, coreunit);
1339 if (!GOODIDX(idx))
1340 return (NULL);
1342 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1343 return sb_setcoreidx(sih, idx);
1344 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1345 return ai_setcoreidx(sih, idx);
1346 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1347 return ub_setcoreidx(sih, idx);
1348 else {
1349 ASSERT(0);
1350 return NULL;
1354 void *
1355 si_setcoreidx(si_t *sih, uint coreidx)
1357 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1358 return sb_setcoreidx(sih, coreidx);
1359 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1360 return ai_setcoreidx(sih, coreidx);
1361 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1362 return ub_setcoreidx(sih, coreidx);
1363 else {
1364 ASSERT(0);
1365 return NULL;
1369 /* Turn off interrupt as required by sb_setcore, before switch core */
1370 void *
1371 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1373 void *cc;
1374 si_info_t *sii;
1376 sii = SI_INFO(sih);
1378 if (SI_FAST(sii)) {
1379 /* Overloading the origidx variable to remember the coreid,
1380 * this works because the core ids cannot be confused with
1381 * core indices.
1383 *origidx = coreid;
1384 if (coreid == CC_CORE_ID)
1385 return (void *)CCREGS_FAST(sii);
1386 else if (coreid == sih->buscoretype)
1387 return (void *)PCIEREGS(sii);
1389 INTR_OFF(sii, *intr_val);
1390 *origidx = sii->curidx;
1391 cc = si_setcore(sih, coreid, 0);
1392 ASSERT(cc != NULL);
1394 return cc;
1397 /* restore coreidx and restore interrupt */
1398 void
1399 si_restore_core(si_t *sih, uint coreid, uint intr_val)
1401 si_info_t *sii;
1403 sii = SI_INFO(sih);
1404 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1405 return;
1407 si_setcoreidx(sih, coreid);
1408 INTR_RESTORE(sii, intr_val);
1412 si_numaddrspaces(si_t *sih)
1414 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1415 return sb_numaddrspaces(sih);
1416 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1417 return ai_numaddrspaces(sih);
1418 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1419 return ub_numaddrspaces(sih);
1420 else {
1421 ASSERT(0);
1422 return 0;
1426 uint32
1427 si_addrspace(si_t *sih, uint asidx)
1429 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1430 return sb_addrspace(sih, asidx);
1431 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1432 return ai_addrspace(sih, asidx);
1433 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1434 return ub_addrspace(sih, asidx);
1435 else {
1436 ASSERT(0);
1437 return 0;
1441 uint32
1442 si_addrspacesize(si_t *sih, uint asidx)
1444 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1445 return sb_addrspacesize(sih, asidx);
1446 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1447 return ai_addrspacesize(sih, asidx);
1448 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1449 return ub_addrspacesize(sih, asidx);
1450 else {
1451 ASSERT(0);
1452 return 0;
1456 void
1457 si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
1459 /* Only supported for SOCI_AI */
1460 if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1461 ai_coreaddrspaceX(sih, asidx, addr, size);
1462 else
1463 *size = 0;
1466 uint32
1467 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1469 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1470 return sb_core_cflags(sih, mask, val);
1471 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1472 return ai_core_cflags(sih, mask, val);
1473 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1474 return ub_core_cflags(sih, mask, val);
1475 else {
1476 ASSERT(0);
1477 return 0;
1481 void
1482 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1484 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1485 sb_core_cflags_wo(sih, mask, val);
1486 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1487 ai_core_cflags_wo(sih, mask, val);
1488 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1489 ub_core_cflags_wo(sih, mask, val);
1490 else
1491 ASSERT(0);
1494 uint32
1495 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1497 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1498 return sb_core_sflags(sih, mask, val);
1499 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1500 return ai_core_sflags(sih, mask, val);
1501 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1502 return ub_core_sflags(sih, mask, val);
1503 else {
1504 ASSERT(0);
1505 return 0;
1509 bool
1510 si_iscoreup(si_t *sih)
1512 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1513 return sb_iscoreup(sih);
1514 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1515 return ai_iscoreup(sih);
1516 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1517 return ub_iscoreup(sih);
1518 else {
1519 ASSERT(0);
1520 return FALSE;
1524 uint
1525 si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
1527 /* only for AI back plane chips */
1528 if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1529 return (ai_wrap_reg(sih, offset, mask, val));
1530 return 0;
1533 uint
1534 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1536 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1537 return sb_corereg(sih, coreidx, regoff, mask, val);
1538 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1539 return ai_corereg(sih, coreidx, regoff, mask, val);
1540 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1541 return ub_corereg(sih, coreidx, regoff, mask, val);
1542 else {
1543 ASSERT(0);
1544 return 0;
1548 void
1549 si_core_disable(si_t *sih, uint32 bits)
1551 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1552 sb_core_disable(sih, bits);
1553 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1554 ai_core_disable(sih, bits);
1555 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1556 ub_core_disable(sih, bits);
1559 void
1560 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1562 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1563 sb_core_reset(sih, bits, resetbits);
1564 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1565 ai_core_reset(sih, bits, resetbits);
1566 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1567 ub_core_reset(sih, bits, resetbits);
1570 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1572 si_corebist(si_t *sih)
1574 uint32 cflags;
1575 int result = 0;
1577 /* Read core control flags */
1578 cflags = si_core_cflags(sih, 0, 0);
1580 /* Set bist & fgc */
1581 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1583 /* Wait for bist done */
1584 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1586 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1587 result = BCME_ERROR;
1589 /* Reset core control flags */
1590 si_core_cflags(sih, 0xffff, cflags);
1592 return result;
1595 static uint32
1596 BCMINITFN(factor6)(uint32 x)
1598 switch (x) {
1599 case CC_F6_2: return 2;
1600 case CC_F6_3: return 3;
1601 case CC_F6_4: return 4;
1602 case CC_F6_5: return 5;
1603 case CC_F6_6: return 6;
1604 case CC_F6_7: return 7;
1605 default: return 0;
1609 /* calculate the speed the SI would run at given a set of clockcontrol values */
1610 uint32
1611 BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m)
1613 uint32 n1, n2, clock, m1, m2, m3, mc;
1615 n1 = n & CN_N1_MASK;
1616 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1618 if (pll_type == PLL_TYPE6) {
1619 if (m & CC_T6_MMASK)
1620 return CC_T6_M1;
1621 else
1622 return CC_T6_M0;
1623 } else if ((pll_type == PLL_TYPE1) ||
1624 (pll_type == PLL_TYPE3) ||
1625 (pll_type == PLL_TYPE4) ||
1626 (pll_type == PLL_TYPE7)) {
1627 n1 = factor6(n1);
1628 n2 += CC_F5_BIAS;
1629 } else if (pll_type == PLL_TYPE2) {
1630 n1 += CC_T2_BIAS;
1631 n2 += CC_T2_BIAS;
1632 ASSERT((n1 >= 2) && (n1 <= 7));
1633 ASSERT((n2 >= 5) && (n2 <= 23));
1634 } else if (pll_type == PLL_TYPE5) {
1635 return (100000000);
1636 } else
1637 ASSERT(0);
1638 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1639 if ((pll_type == PLL_TYPE3) ||
1640 (pll_type == PLL_TYPE7)) {
1641 clock = CC_CLOCK_BASE2 * n1 * n2;
1642 } else
1643 clock = CC_CLOCK_BASE1 * n1 * n2;
1645 if (clock == 0)
1646 return 0;
1648 m1 = m & CC_M1_MASK;
1649 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1650 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1651 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1653 if ((pll_type == PLL_TYPE1) ||
1654 (pll_type == PLL_TYPE3) ||
1655 (pll_type == PLL_TYPE4) ||
1656 (pll_type == PLL_TYPE7)) {
1657 m1 = factor6(m1);
1658 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1659 m2 += CC_F5_BIAS;
1660 else
1661 m2 = factor6(m2);
1662 m3 = factor6(m3);
1664 switch (mc) {
1665 case CC_MC_BYPASS: return (clock);
1666 case CC_MC_M1: return (clock / m1);
1667 case CC_MC_M1M2: return (clock / (m1 * m2));
1668 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
1669 case CC_MC_M1M3: return (clock / (m1 * m3));
1670 default: return (0);
1672 } else {
1673 ASSERT(pll_type == PLL_TYPE2);
1675 m1 += CC_T2_BIAS;
1676 m2 += CC_T2M2_BIAS;
1677 m3 += CC_T2_BIAS;
1678 ASSERT((m1 >= 2) && (m1 <= 7));
1679 ASSERT((m2 >= 3) && (m2 <= 10));
1680 ASSERT((m3 >= 2) && (m3 <= 7));
1682 if ((mc & CC_T2MC_M1BYP) == 0)
1683 clock /= m1;
1684 if ((mc & CC_T2MC_M2BYP) == 0)
1685 clock /= m2;
1686 if ((mc & CC_T2MC_M3BYP) == 0)
1687 clock /= m3;
1689 return (clock);
1693 bool si_read_pmu_autopll(si_t *sih)
1695 si_info_t *sii;
1696 sii = SI_INFO(sih);
1697 return (si_pmu_is_autoresetphyclk_disabled(sih, sii->osh));
1700 uint32
1701 BCMINITFN(si_clock)(si_t *sih)
1703 si_info_t *sii;
1704 chipcregs_t *cc;
1705 uint32 n, m;
1706 uint idx;
1707 uint32 pll_type, rate;
1708 uint intr_val = 0;
1710 if (CHIPID(sih->chip) == BCM4707_CHIP_ID) {
1711 if (sih->chippkg == BCM4709_PKG_ID) {
1712 return NS_SI_CLOCK;
1713 } else
1714 return NS_SLOW_SI_CLOCK;
1717 sii = SI_INFO(sih);
1718 INTR_OFF(sii, intr_val);
1719 if (PMUCTL_ENAB(sih)) {
1720 rate = si_pmu_si_clock(sih, sii->osh);
1721 goto exit;
1724 idx = sii->curidx;
1725 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1726 ASSERT(cc != NULL);
1728 n = R_REG(sii->osh, &cc->clockcontrol_n);
1729 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1730 if (pll_type == PLL_TYPE6)
1731 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1732 else if (pll_type == PLL_TYPE3)
1733 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1734 else
1735 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1737 /* calculate rate */
1738 rate = si_clock_rate(pll_type, n, m);
1740 if (pll_type == PLL_TYPE3)
1741 rate = rate / 2;
1743 /* switch back to previous core */
1744 si_setcoreidx(sih, idx);
1745 exit:
1746 INTR_RESTORE(sii, intr_val);
1748 return rate;
1751 uint32
1752 BCMINITFN(si_alp_clock)(si_t *sih)
1754 if (PMUCTL_ENAB(sih))
1755 return si_pmu_alp_clock(sih, si_osh(sih));
1756 else if (CHIPID(sih->chip) == BCM4707_CHIP_ID) {
1757 if (sih->chippkg == BCM4709_PKG_ID)
1758 return NS_ALP_CLOCK;
1759 else
1760 return NS_SLOW_ALP_CLOCK;
1763 return ALP_CLOCK;
1766 uint32
1767 BCMINITFN(si_ilp_clock)(si_t *sih)
1769 if (PMUCTL_ENAB(sih))
1770 return si_pmu_ilp_clock(sih, si_osh(sih));
1772 return ILP_CLOCK;
1775 /* set chip watchdog reset timer to fire in 'ticks' */
1776 void
1777 si_watchdog(si_t *sih, uint ticks)
1779 uint nb, maxt;
1781 if (PMUCTL_ENAB(sih)) {
1783 #if !defined(_CFE_) || defined(CFG_WL)
1784 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1785 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1786 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1787 si_setcore(sih, USB20D_CORE_ID, 0);
1788 si_core_disable(sih, 1);
1789 si_setcore(sih, CC_CORE_ID, 0);
1791 #endif /* !_CFE_ || CFG_WL */
1793 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
1794 nb = 32;
1795 else
1796 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1797 /* The mips compiler uses the sllv instruction,
1798 * so we specially handle the 32-bit case.
1800 if (nb == 32)
1801 maxt = 0xffffffff;
1802 else
1803 maxt = ((1 << nb) - 1);
1805 if (ticks == 1)
1806 ticks = 2;
1807 else if (ticks > maxt)
1808 ticks = maxt;
1810 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1811 } else {
1812 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1813 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1814 maxt = (1 << 28) - 1;
1815 if (ticks > maxt)
1816 ticks = maxt;
1818 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1822 /* trigger watchdog reset after ms milliseconds */
1823 void
1824 si_watchdog_ms(si_t *sih, uint32 ms)
1826 si_watchdog(sih, wd_msticks * ms);
1829 uint32
1830 si_watchdog_msticks(void)
1832 return wd_msticks;
1835 bool
1836 si_taclear(si_t *sih, bool details)
1838 #if defined(BCMDBG_ERR) || defined(BCMASSERT_SUPPORT)
1839 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1840 return sb_taclear(sih, details);
1841 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1842 return FALSE;
1843 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1844 return FALSE;
1845 else {
1846 ASSERT(0);
1847 return FALSE;
1849 #else
1850 return FALSE;
1851 #endif
1854 uint16
1855 BCMATTACHFN(si_d11_devid)(si_t *sih)
1857 si_info_t *sii = SI_INFO(sih);
1858 uint16 device;
1860 /* Fix device id for dual band BCM4328 */
1861 if (CHIPID(sih->chip) == BCM4328_CHIP_ID &&
1862 (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID))
1863 device = BCM4328_D11DUAL_ID;
1864 else {
1865 /* normal case: nvram variable with devpath->devid->wl0id */
1866 if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0)
1868 /* Get devid from OTP/SPROM depending on where the SROM is read */
1869 else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0)
1871 /* no longer support wl0id, but keep the code here for backward compatibility. */
1872 else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0)
1874 else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) {
1875 /* Chip specific conversion */
1876 if (sih->chippkg == BCM4712SMALL_PKG_ID)
1877 device = BCM4306_D11G_ID;
1878 else
1879 device = BCM4306_D11DUAL_ID;
1880 } else {
1881 /* ignore it */
1882 device = 0xffff;
1885 return device;
1889 BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
1890 uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
1891 uint8 *pciheader)
1893 uint16 vendor = 0xffff, device = 0xffff;
1894 uint8 class, subclass, progif = 0;
1895 uint8 header = PCI_HEADER_NORMAL;
1896 uint32 core = si_coreid(sih);
1898 /* Verify whether the function exists for the core */
1899 if (func >= (uint)(core == USB20H_CORE_ID ? 2 : 1))
1900 return BCME_ERROR;
1902 /* Known vendor translations */
1903 switch (si_corevendor(sih)) {
1904 case SB_VEND_BCM:
1905 case MFGID_BRCM:
1906 vendor = VENDOR_BROADCOM;
1907 break;
1908 default:
1909 return BCME_ERROR;
1912 /* Determine class based on known core codes */
1913 switch (core) {
1914 case ENET_CORE_ID:
1915 class = PCI_CLASS_NET;
1916 subclass = PCI_NET_ETHER;
1917 device = BCM47XX_ENET_ID;
1918 break;
1919 case GIGETH_CORE_ID:
1920 class = PCI_CLASS_NET;
1921 subclass = PCI_NET_ETHER;
1922 device = BCM47XX_GIGETH_ID;
1923 break;
1924 case GMAC_CORE_ID:
1925 class = PCI_CLASS_NET;
1926 subclass = PCI_NET_ETHER;
1927 device = BCM47XX_GMAC_ID;
1928 break;
1929 case SDRAM_CORE_ID:
1930 case MEMC_CORE_ID:
1931 case DMEMC_CORE_ID:
1932 case SOCRAM_CORE_ID:
1933 class = PCI_CLASS_MEMORY;
1934 subclass = PCI_MEMORY_RAM;
1935 device = (uint16)core;
1936 break;
1937 case PCI_CORE_ID:
1938 case PCIE_CORE_ID:
1939 case PCIE2_CORE_ID:
1940 class = PCI_CLASS_BRIDGE;
1941 subclass = PCI_BRIDGE_PCI;
1942 device = (uint16)core;
1943 header = PCI_HEADER_BRIDGE;
1944 break;
1945 case MIPS33_CORE_ID:
1946 case MIPS74K_CORE_ID:
1947 class = PCI_CLASS_CPU;
1948 subclass = PCI_CPU_MIPS;
1949 device = (uint16)core;
1950 break;
1951 case CODEC_CORE_ID:
1952 class = PCI_CLASS_COMM;
1953 subclass = PCI_COMM_MODEM;
1954 device = BCM47XX_V90_ID;
1955 break;
1956 case I2S_CORE_ID:
1957 class = PCI_CLASS_MMEDIA;
1958 subclass = PCI_MMEDIA_AUDIO;
1959 device = BCM47XX_AUDIO_ID;
1960 break;
1961 case USB_CORE_ID:
1962 case USB11H_CORE_ID:
1963 class = PCI_CLASS_SERIAL;
1964 subclass = PCI_SERIAL_USB;
1965 progif = 0x10; /* OHCI */
1966 device = BCM47XX_USBH_ID;
1967 break;
1968 case USB20H_CORE_ID:
1969 class = PCI_CLASS_SERIAL;
1970 subclass = PCI_SERIAL_USB;
1971 progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
1972 device = BCM47XX_USB20H_ID;
1973 header = 0x80; /* multifunction */
1974 break;
1975 case IPSEC_CORE_ID:
1976 class = PCI_CLASS_CRYPT;
1977 subclass = PCI_CRYPT_NETWORK;
1978 device = BCM47XX_IPSEC_ID;
1979 break;
1980 case NS_USB20_CORE_ID:
1981 class = PCI_CLASS_SERIAL;
1982 subclass = PCI_SERIAL_USB;
1983 progif = 0x20; /* EHCI */
1984 device = BCM47XX_USB20H_ID;
1985 break;
1986 case NS_USB30_CORE_ID:
1987 class = PCI_CLASS_SERIAL;
1988 subclass = PCI_SERIAL_USB;
1989 progif = 0x30; /* XHCI */
1990 device = BCM47XX_USB30H_ID;
1991 break;
1992 case ROBO_CORE_ID:
1993 /* Don't use class NETWORK, so wl/et won't attempt to recognize it */
1994 class = PCI_CLASS_COMM;
1995 subclass = PCI_COMM_OTHER;
1996 device = BCM47XX_ROBO_ID;
1997 break;
1998 case CC_CORE_ID:
1999 class = PCI_CLASS_MEMORY;
2000 subclass = PCI_MEMORY_FLASH;
2001 device = (uint16)core;
2002 break;
2003 case SATAXOR_CORE_ID:
2004 class = PCI_CLASS_XOR;
2005 subclass = PCI_XOR_QDMA;
2006 device = BCM47XX_SATAXOR_ID;
2007 break;
2008 case ATA100_CORE_ID:
2009 class = PCI_CLASS_DASDI;
2010 subclass = PCI_DASDI_IDE;
2011 device = BCM47XX_ATA100_ID;
2012 break;
2013 case USB11D_CORE_ID:
2014 class = PCI_CLASS_SERIAL;
2015 subclass = PCI_SERIAL_USB;
2016 device = BCM47XX_USBD_ID;
2017 break;
2018 case USB20D_CORE_ID:
2019 class = PCI_CLASS_SERIAL;
2020 subclass = PCI_SERIAL_USB;
2021 device = BCM47XX_USB20D_ID;
2022 break;
2023 case D11_CORE_ID:
2024 class = PCI_CLASS_NET;
2025 subclass = PCI_NET_OTHER;
2026 device = si_d11_devid(sih);
2027 break;
2029 default:
2030 class = subclass = progif = 0xff;
2031 device = (uint16)core;
2032 break;
2035 *pcivendor = vendor;
2036 *pcidevice = device;
2037 *pciclass = class;
2038 *pcisubclass = subclass;
2039 *pciprogif = progif;
2040 *pciheader = header;
2042 return 0;
2045 #if defined(BCMDBG)
2046 /* print interesting sbconfig registers */
2047 void
2048 si_dumpregs(si_t *sih, struct bcmstrbuf *b)
2050 si_info_t *sii;
2051 uint origidx, intr_val = 0;
2053 sii = SI_INFO(sih);
2054 origidx = sii->curidx;
2056 INTR_OFF(sii, intr_val);
2057 if (CHIPTYPE(sih->socitype) == SOCI_SB)
2058 sb_dumpregs(sih, b);
2059 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2060 ai_dumpregs(sih, b);
2061 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
2062 ub_dumpregs(sih, b);
2063 else
2064 ASSERT(0);
2066 si_setcoreidx(sih, origidx);
2067 INTR_RESTORE(sii, intr_val);
2069 #endif
2071 #ifdef BCMDBG
2072 void
2073 si_view(si_t *sih, bool verbose)
2075 if (CHIPTYPE(sih->socitype) == SOCI_SB)
2076 sb_view(sih, verbose);
2077 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2078 ai_view(sih, verbose);
2079 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
2080 ub_view(sih, verbose);
2081 else
2082 ASSERT(0);
2085 void
2086 si_viewall(si_t *sih, bool verbose)
2088 si_info_t *sii;
2089 uint curidx, i;
2090 uint intr_val = 0;
2092 sii = SI_INFO(sih);
2093 curidx = sii->curidx;
2095 INTR_OFF(sii, intr_val);
2096 if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2097 ai_viewall(sih, verbose);
2098 else {
2099 SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores));
2100 for (i = 0; i < sii->numcores; i++) {
2101 si_setcoreidx(sih, i);
2102 si_view(sih, verbose);
2105 si_setcoreidx(sih, curidx);
2106 INTR_RESTORE(sii, intr_val);
2108 #endif /* BCMDBG */
2110 /* return the slow clock source - LPO, XTAL, or PCI */
2111 static uint
2112 si_slowclk_src(si_info_t *sii)
2114 chipcregs_t *cc;
2116 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2118 if (sii->pub.ccrev < 6) {
2119 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
2120 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
2121 PCI_CFG_GPIO_SCS))
2122 return (SCC_SS_PCI);
2123 else
2124 return (SCC_SS_XTAL);
2125 } else if (sii->pub.ccrev < 10) {
2126 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
2127 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
2128 } else /* Insta-clock */
2129 return (SCC_SS_XTAL);
2132 /* return the ILP (slowclock) min or max frequency */
2133 static uint
2134 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
2136 uint32 slowclk;
2137 uint div;
2139 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2141 /* shouldn't be here unless we've established the chip has dynamic clk control */
2142 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
2144 slowclk = si_slowclk_src(sii);
2145 if (sii->pub.ccrev < 6) {
2146 if (slowclk == SCC_SS_PCI)
2147 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
2148 else
2149 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
2150 } else if (sii->pub.ccrev < 10) {
2151 div = 4 *
2152 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
2153 if (slowclk == SCC_SS_LPO)
2154 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
2155 else if (slowclk == SCC_SS_XTAL)
2156 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
2157 else if (slowclk == SCC_SS_PCI)
2158 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
2159 else
2160 ASSERT(0);
2161 } else {
2162 /* Chipc rev 10 is InstaClock */
2163 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
2164 div = 4 * (div + 1);
2165 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
2167 return (0);
2170 static void
2171 BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs)
2173 chipcregs_t *cc = (chipcregs_t *)chipcregs;
2174 uint slowmaxfreq, pll_delay, slowclk;
2175 uint pll_on_delay, fref_sel_delay;
2177 pll_delay = PLL_DELAY;
2179 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
2180 * since the xtal will also be powered down by dynamic clk control logic.
2183 slowclk = si_slowclk_src(sii);
2184 if (slowclk != SCC_SS_XTAL)
2185 pll_delay += XTAL_ON_DELAY;
2187 /* Starting with 4318 it is ILP that is used for the delays */
2188 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
2190 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
2191 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
2193 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
2194 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
2197 /* initialize power control delay registers */
2198 void
2199 BCMINITFN(si_clkctl_init)(si_t *sih)
2201 si_info_t *sii;
2202 uint origidx = 0;
2203 chipcregs_t *cc;
2204 bool fast;
2206 if (!CCCTL_ENAB(sih))
2207 return;
2209 sii = SI_INFO(sih);
2210 fast = SI_FAST(sii);
2211 if (!fast) {
2212 origidx = sii->curidx;
2213 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2214 return;
2215 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2216 return;
2217 ASSERT(cc != NULL);
2219 /* set all Instaclk chip ILP to 1 MHz */
2220 if (sih->ccrev >= 10)
2221 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
2222 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
2224 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
2226 OSL_DELAY(20000);
2228 if (!fast)
2229 si_setcoreidx(sih, origidx);
2232 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
2233 uint16
2234 BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih)
2236 si_info_t *sii;
2237 uint origidx = 0;
2238 chipcregs_t *cc;
2239 uint slowminfreq;
2240 uint16 fpdelay;
2241 uint intr_val = 0;
2242 bool fast;
2244 sii = SI_INFO(sih);
2245 if (PMUCTL_ENAB(sih)) {
2246 INTR_OFF(sii, intr_val);
2247 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
2248 INTR_RESTORE(sii, intr_val);
2249 return fpdelay;
2252 if (!CCCTL_ENAB(sih))
2253 return 0;
2255 fast = SI_FAST(sii);
2256 fpdelay = 0;
2257 if (!fast) {
2258 origidx = sii->curidx;
2259 INTR_OFF(sii, intr_val);
2260 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2261 goto done;
2263 else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2264 goto done;
2265 ASSERT(cc != NULL);
2267 slowminfreq = si_slowclk_freq(sii, FALSE, cc);
2268 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
2269 (slowminfreq - 1)) / slowminfreq;
2271 done:
2272 if (!fast) {
2273 si_setcoreidx(sih, origidx);
2274 INTR_RESTORE(sii, intr_val);
2276 return fpdelay;
2279 /* turn primary xtal and/or pll off/on */
2281 si_clkctl_xtal(si_t *sih, uint what, bool on)
2283 si_info_t *sii;
2284 uint32 in, out, outen;
2286 sii = SI_INFO(sih);
2288 switch (BUSTYPE(sih->bustype)) {
2291 case PCMCIA_BUS:
2292 return (0);
2295 case PCI_BUS:
2296 /* pcie core doesn't have any mapping to control the xtal pu */
2297 if (PCIE(sii))
2298 return -1;
2300 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
2301 out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
2302 outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32));
2305 * Avoid glitching the clock if GPRS is already using it.
2306 * We can't actually read the state of the PLLPD so we infer it
2307 * by the value of XTAL_PU which *is* readable via gpioin.
2309 if (on && (in & PCI_CFG_GPIO_XTAL))
2310 return (0);
2312 if (what & XTAL)
2313 outen |= PCI_CFG_GPIO_XTAL;
2314 if (what & PLL)
2315 outen |= PCI_CFG_GPIO_PLL;
2317 if (on) {
2318 /* turn primary xtal on */
2319 if (what & XTAL) {
2320 out |= PCI_CFG_GPIO_XTAL;
2321 if (what & PLL)
2322 out |= PCI_CFG_GPIO_PLL;
2323 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2324 sizeof(uint32), out);
2325 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
2326 sizeof(uint32), outen);
2327 OSL_DELAY(XTAL_ON_DELAY);
2330 /* turn pll on */
2331 if (what & PLL) {
2332 out &= ~PCI_CFG_GPIO_PLL;
2333 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2334 sizeof(uint32), out);
2335 OSL_DELAY(2000);
2337 } else {
2338 if (what & XTAL)
2339 out &= ~PCI_CFG_GPIO_XTAL;
2340 if (what & PLL)
2341 out |= PCI_CFG_GPIO_PLL;
2342 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out);
2343 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32),
2344 outen);
2346 return 0;
2348 default:
2349 return (-1);
2352 return (0);
2356 * clock control policy function throught chipcommon
2358 * set dynamic clk control mode (forceslow, forcefast, dynamic)
2359 * returns true if we are forcing fast clock
2360 * this is a wrapper over the next internal function
2361 * to allow flexible policy settings for outside caller
2363 bool
2364 si_clkctl_cc(si_t *sih, uint mode)
2366 si_info_t *sii;
2368 sii = SI_INFO(sih);
2370 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2371 if (sih->ccrev < 6)
2372 return FALSE;
2374 if (PCI_FORCEHT(sii))
2375 return (mode == CLK_FAST);
2377 return _si_clkctl_cc(sii, mode);
2380 /* clk control mechanism through chipcommon, no policy checking */
2381 static bool
2382 _si_clkctl_cc(si_info_t *sii, uint mode)
2384 uint origidx = 0;
2385 chipcregs_t *cc;
2386 uint32 scc;
2387 uint intr_val = 0;
2388 bool fast = SI_FAST(sii);
2390 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2391 if (sii->pub.ccrev < 6)
2392 return (FALSE);
2394 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
2395 ASSERT(sii->pub.ccrev != 10);
2397 if (!fast) {
2398 INTR_OFF(sii, intr_val);
2399 origidx = sii->curidx;
2401 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
2402 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
2403 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
2404 goto done;
2406 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
2407 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
2408 goto done;
2409 ASSERT(cc != NULL);
2411 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
2412 goto done;
2414 switch (mode) {
2415 case CLK_FAST: /* FORCEHT, fast (pll) clock */
2416 if (sii->pub.ccrev < 10) {
2417 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2418 si_clkctl_xtal(&sii->pub, XTAL, ON);
2419 SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
2420 } else if (sii->pub.ccrev < 20) {
2421 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
2422 } else {
2423 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
2426 /* wait for the PLL */
2427 if (PMUCTL_ENAB(&sii->pub)) {
2428 uint32 htavail = CCS_HTAVAIL;
2429 if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2430 htavail = CCS0_HTAVAIL;
2431 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0),
2432 PMU_MAX_TRANSITION_DLY);
2433 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
2434 } else {
2435 OSL_DELAY(PLL_DELAY);
2437 break;
2439 case CLK_DYNAMIC: /* enable dynamic clock control */
2440 if (sii->pub.ccrev < 10) {
2441 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
2442 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
2443 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
2444 scc |= SCC_XC;
2445 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
2447 /* for dynamic control, we have to release our xtal_pu "force on" */
2448 if (scc & SCC_XC)
2449 si_clkctl_xtal(&sii->pub, XTAL, OFF);
2450 } else if (sii->pub.ccrev < 20) {
2451 /* Instaclock */
2452 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
2453 } else {
2454 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
2457 /* wait for the PLL */
2458 if (PMUCTL_ENAB(&sii->pub)) {
2459 uint32 htavail = CCS_HTAVAIL;
2460 if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2461 htavail = CCS0_HTAVAIL;
2462 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) != 0),
2463 PMU_MAX_TRANSITION_DLY);
2464 ASSERT(!(R_REG(sii->osh, &cc->clk_ctl_st) & htavail));
2465 } else {
2466 OSL_DELAY(PLL_DELAY);
2469 break;
2471 default:
2472 ASSERT(0);
2475 done:
2476 if (!fast) {
2477 si_setcoreidx(&sii->pub, origidx);
2478 INTR_RESTORE(sii, intr_val);
2480 return (mode == CLK_FAST);
2483 /* Build device path. Support SI, PCI, and JTAG for now. */
2485 BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size)
2487 int slen;
2489 ASSERT(path != NULL);
2490 ASSERT(size >= SI_DEVPATH_BUFSZ);
2492 if (!path || size <= 0)
2493 return -1;
2495 switch (BUSTYPE(sih->bustype)) {
2496 case SI_BUS:
2497 case JTAG_BUS:
2498 slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih));
2499 break;
2500 case PCI_BUS:
2501 ASSERT((SI_INFO(sih))->osh != NULL);
2502 slen = snprintf(path, (size_t)size, "pci/%u/%u/",
2503 OSL_PCI_BUS((SI_INFO(sih))->osh),
2504 OSL_PCI_SLOT((SI_INFO(sih))->osh));
2505 break;
2506 case PCMCIA_BUS:
2507 SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
2508 SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
2509 slen = snprintf(path, (size_t)size, "pc/1/1/");
2510 break;
2511 default:
2512 slen = -1;
2513 ASSERT(0);
2514 break;
2517 if (slen < 0 || slen >= size) {
2518 path[0] = '\0';
2519 return -1;
2522 return 0;
2525 char *
2526 BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name)
2528 char pathname[SI_DEVPATH_BUFSZ + 32];
2529 char devpath[SI_DEVPATH_BUFSZ + 32];
2530 char *p;
2531 int idx;
2532 int len1;
2533 int len2;
2535 /* try to get compact devpath if it exist */
2536 if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) {
2537 /* eliminate ending '/' (if present) */
2538 len1 = strlen(devpath);
2539 if (devpath[len1 - 1] == '/')
2540 len1--;
2542 for (idx = 0; idx < SI_MAXCORES; idx++) {
2543 snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx);
2544 if ((p = getvar(NULL, pathname)) == NULL)
2545 continue;
2547 /* eliminate ending '/' (if present) */
2548 len2 = strlen(p);
2549 if (p[len2 - 1] == '/')
2550 len2--;
2552 /* check that both lengths match and if so compare */
2553 /* the strings (minus trailing '/'s if present */
2554 if ((len1 == len2) && (memcmp(p, devpath, len1) == 0)) {
2555 snprintf(varname, var_len, "%d:%s", idx, name);
2556 return varname;
2561 return NULL;
2564 /* Get a variable, but only if it has a devpath prefix */
2565 char *
2566 BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name)
2568 char varname[SI_DEVPATH_BUFSZ + 32];
2569 char *val;
2571 si_devpathvar(sih, varname, sizeof(varname), name);
2573 if ((val = getvar(NULL, varname)) != NULL)
2574 return val;
2576 /* try to get compact devpath if it exist */
2577 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2578 return NULL;
2580 return (getvar(NULL, varname));
2583 /* Get a variable, but only if it has a devpath prefix */
2585 BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name)
2587 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
2588 return (getintvar(NULL, name));
2589 #else
2590 char varname[SI_DEVPATH_BUFSZ + 32];
2591 int val;
2593 si_devpathvar(sih, varname, sizeof(varname), name);
2595 if ((val = getintvar(NULL, varname)) != 0)
2596 return val;
2598 /* try to get compact devpath if it exist */
2599 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2600 return 0;
2602 return (getintvar(NULL, varname));
2603 #endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
2606 #ifndef DONGLEBUILD
2607 char *
2608 si_getnvramflvar(si_t *sih, const char *name)
2610 return (getvar(NULL, name));
2612 #endif /* DONGLEBUILD */
2614 /* Concatenate the dev path with a varname into the given 'var' buffer
2615 * and return the 'var' pointer.
2616 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
2617 * On overflow, the first char will be set to '\0'.
2619 static char *
2620 BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name)
2622 uint path_len;
2624 if (!var || len <= 0)
2625 return var;
2627 if (si_devpath(sih, var, len) == 0) {
2628 path_len = strlen(var);
2630 if (strlen(name) + 1 > (uint)(len - path_len))
2631 var[0] = '\0';
2632 else
2633 strncpy(var + path_len, name, len - path_len - 1);
2636 return var;
2640 uint32
2641 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
2643 si_info_t *sii;
2645 sii = SI_INFO(sih);
2647 if (!PCIE(sii)) {
2648 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2649 return 0;
2652 return pcicore_pciereg(sii->pch, offset, mask, val, type);
2655 uint32
2656 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
2658 si_info_t *sii;
2660 sii = SI_INFO(sih);
2662 if (!PCIE(sii)) {
2663 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2664 return 0;
2667 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
2671 /* return TRUE if PCIE capability exists in the pci config space */
2672 static bool
2673 si_ispcie(si_info_t *sii)
2675 uint8 cap_ptr;
2677 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2678 return FALSE;
2680 cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL);
2681 if (!cap_ptr)
2682 return FALSE;
2684 return TRUE;
2687 /* Wake-on-wireless-LAN (WOWL) support functions */
2688 /* Enable PME generation and disable clkreq */
2689 void
2690 si_pci_pmeen(si_t *sih)
2692 si_info_t *sii;
2694 sii = SI_INFO(sih);
2696 pcicore_pmeen(sii->pch);
2699 /* Return TRUE if PME status is set */
2700 bool
2701 si_pci_pmestat(si_t *sih)
2703 si_info_t *sii;
2705 sii = SI_INFO(sih);
2707 return pcicore_pmestat(sii->pch);
2710 /* Disable PME generation, clear the PME status bit if set */
2711 void
2712 si_pci_pmeclr(si_t *sih)
2714 si_info_t *sii;
2716 sii = SI_INFO(sih);
2718 pcicore_pmeclr(sii->pch);
2721 void
2722 si_pci_pmestatclr(si_t *sih)
2724 si_info_t *sii;
2726 sii = SI_INFO(sih);
2728 pcicore_pmestatclr(sii->pch);
2731 /* initialize the pcmcia core */
2732 void
2733 si_pcmcia_init(si_t *sih)
2735 si_info_t *sii;
2736 uint8 cor = 0;
2738 sii = SI_INFO(sih);
2740 /* enable d11 mac interrupts */
2741 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2742 cor |= COR_IRQEN | COR_FUNEN;
2743 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2748 bool
2749 BCMATTACHFN(si_pci_war16165)(si_t *sih)
2751 si_info_t *sii;
2753 sii = SI_INFO(sih);
2755 return (PCI(sii) && (sih->buscorerev <= 10));
2758 /* Disable pcie_war_ovr for some platforms (sigh!)
2759 * This is for boards that have BFL2_PCIEWAR_OVR set
2760 * but are in systems that still want the benefits of ASPM
2761 * Note that this should be done AFTER si_doattach
2763 void
2764 si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
2766 si_info_t *sii;
2768 sii = SI_INFO(sih);
2770 if (!PCIE_GEN1(sii))
2771 return;
2773 pcie_war_ovr_aspm_update(sii->pch, aspm);
2776 void
2777 si_pcie_power_save_enable(si_t *sih, bool enable)
2779 si_info_t *sii;
2781 sii = SI_INFO(sih);
2783 if (!PCIE_GEN1(sii))
2784 return;
2786 pcie_power_save_enable(sii->pch, enable);
2789 void
2790 si_pcie_set_maxpayload_size(si_t *sih, uint16 size)
2792 si_info_t *sii;
2794 sii = SI_INFO(sih);
2796 if (!PCIE(sii))
2797 return;
2799 pcie_set_maxpayload_size(sii->pch, size);
2802 uint16
2803 si_pcie_get_maxpayload_size(si_t *sih)
2805 si_info_t *sii;
2807 sii = SI_INFO(sih);
2809 if (!PCIE(sii))
2810 return (0);
2812 return pcie_get_maxpayload_size(sii->pch);
2815 void
2816 si_pcie_set_request_size(si_t *sih, uint16 size)
2818 si_info_t *sii;
2820 sii = SI_INFO(sih);
2822 if (!PCIE(sii))
2823 return;
2825 pcie_set_request_size(sii->pch, size);
2828 uint16
2829 si_pcie_get_request_size(si_t *sih)
2831 si_info_t *sii;
2833 sii = SI_INFO(sih);
2835 if (!PCIE_GEN1(sii))
2836 return (0);
2838 return pcie_get_request_size(sii->pch);
2842 uint16
2843 si_pcie_get_ssid(si_t *sih)
2845 si_info_t *sii;
2847 sii = SI_INFO(sih);
2849 if (!PCIE_GEN1(sii))
2850 return (0);
2852 return pcie_get_ssid(sii->pch);
2855 uint32
2856 si_pcie_get_bar0(si_t *sih)
2858 si_info_t *sii;
2860 sii = SI_INFO(sih);
2862 if (!PCIE(sii))
2863 return (0);
2865 return pcie_get_bar0(sii->pch);
2869 si_pcie_configspace_cache(si_t *sih)
2871 si_info_t *sii;
2873 sii = SI_INFO(sih);
2875 if (!PCIE(sii))
2876 return -1;
2878 return pcie_configspace_cache(sii->pch);
2882 si_pcie_configspace_restore(si_t *sih)
2884 si_info_t *sii;
2886 sii = SI_INFO(sih);
2888 if (!PCIE(sii))
2889 return -1;
2891 return pcie_configspace_restore(sii->pch);
2895 si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size)
2897 si_info_t *sii;
2899 sii = SI_INFO(sih);
2901 if (!PCIE(sii) || size > PCI_CONFIG_SPACE_SIZE)
2902 return -1;
2904 return pcie_configspace_get(sii->pch, buf, size);
2907 /* back door for other module to override chippkg */
2908 void
2909 si_chippkg_set(si_t *sih, uint val)
2911 si_info_t *sii;
2913 sii = SI_INFO(sih);
2915 sii->pub.chippkg = val;
2918 void
2919 BCMINITFN(si_pci_up)(si_t *sih)
2921 si_info_t *sii;
2923 sii = SI_INFO(sih);
2925 /* if not pci bus, we're done */
2926 if (BUSTYPE(sih->bustype) != PCI_BUS)
2927 return;
2929 if (PCI_FORCEHT(sii))
2930 _si_clkctl_cc(sii, CLK_FAST);
2932 if (PCIE(sii)) {
2933 pcicore_up(sii->pch, SI_PCIUP);
2934 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
2935 (CHIPID(sih->chip) == BCM4312_CHIP_ID))
2936 sb_set_initiator_to((void *)sii, 0x3,
2937 si_findcoreidx((void *)sii, D11_CORE_ID, 0));
2941 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2942 void
2943 BCMUNINITFN(si_pci_sleep)(si_t *sih)
2945 si_info_t *sii;
2947 do_4360_pcie2_war = 0;
2949 sii = SI_INFO(sih);
2951 pcicore_sleep(sii->pch);
2954 /* Unconfigure and/or apply various WARs when going down */
2955 void
2956 BCMINITFN(si_pci_down)(si_t *sih)
2958 si_info_t *sii;
2960 sii = SI_INFO(sih);
2962 /* if not pci bus, we're done */
2963 if (BUSTYPE(sih->bustype) != PCI_BUS)
2964 return;
2966 /* release FORCEHT since chip is going to "down" state */
2967 if (PCI_FORCEHT(sii))
2968 _si_clkctl_cc(sii, CLK_DYNAMIC);
2970 pcicore_down(sii->pch, SI_PCIDOWN);
2974 * Configure the pci core for pci client (NIC) action
2975 * coremask is the bitvec of cores by index to be enabled.
2977 void
2978 BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask)
2980 si_info_t *sii;
2981 sbpciregs_t *pciregs = NULL;
2982 uint32 siflag = 0, w;
2983 uint idx = 0;
2985 sii = SI_INFO(sih);
2987 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2988 return;
2990 ASSERT(PCI(sii) || PCIE(sii));
2991 ASSERT(sii->pub.buscoreidx != BADIDX);
2993 if (PCI(sii)) {
2994 /* get current core index */
2995 idx = sii->curidx;
2997 /* we interrupt on this backplane flag number */
2998 siflag = si_flag(sih);
3000 /* switch over to pci core */
3001 pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx);
3005 * Enable sb->pci interrupts. Assume
3006 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
3008 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
3009 /* pci config write to set this core bit in PCIIntMask */
3010 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
3011 w |= (coremask << PCI_SBIM_SHIFT);
3012 #ifdef USER_MODE
3013 /* User mode operate with interrupt disabled */
3014 w &= !(coremask << PCI_SBIM_SHIFT);
3015 #endif
3016 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
3017 } else {
3018 /* set sbintvec bit for our flag number */
3019 si_setint(sih, siflag);
3022 if (PCI(sii)) {
3023 OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST));
3024 if (sii->pub.buscorerev >= 11) {
3025 OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
3026 w = R_REG(sii->osh, &pciregs->clkrun);
3027 W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL));
3028 w = R_REG(sii->osh, &pciregs->clkrun);
3031 /* switch back to previous core */
3032 si_setcoreidx(sih, idx);
3036 uint8
3037 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
3039 si_info_t *sii;
3041 sii = SI_INFO(sih);
3043 if (!(PCIE(sii)))
3044 return 0;
3046 return pcie_clkreq(sii->pch, mask, val);
3049 uint32
3050 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
3052 si_info_t *sii;
3054 sii = SI_INFO(sih);
3056 if (!PCIE(sii))
3057 return 0;
3059 return pcie_lcreg(sii->pch, mask, val);
3062 uint8
3063 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val)
3065 si_info_t *sii;
3067 sii = SI_INFO(sih);
3069 if (!(PCIE(sii)))
3070 return 0;
3072 return pcie_ltrenable(sii->pch, mask, val);
3075 void
3076 si_pcie_set_error_injection(si_t *sih, uint32 mode)
3078 si_info_t *sii;
3080 sii = SI_INFO(sih);
3082 if (!PCIE(sii))
3083 return;
3085 pcie_set_error_injection(sii->pch, mode);
3088 /* indirect way to read pcie config regs */
3089 uint
3090 si_pcie_readreg(void *sih, uint addrtype, uint offset)
3092 return pcie_readreg(sih, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
3093 addrtype, offset);
3097 * Fixup SROMless PCI device's configuration.
3098 * The current core may be changed upon return.
3101 si_pci_fixcfg(si_t *sih)
3103 uint origidx, pciidx;
3104 sbpciregs_t *pciregs = NULL;
3105 sbpcieregs_t *pcieregs = NULL;
3106 uint16 val16, *reg16 = NULL;
3107 uint32 w;
3109 si_info_t *sii = SI_INFO(sih);
3111 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
3113 if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) {
3114 w = (CHIPREV(sii->pub.chiprev) == 0) ?
3115 CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT;
3116 si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w);
3119 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
3120 /* save the current index */
3121 origidx = si_coreidx(&sii->pub);
3123 /* check 'pi' is correct and fix it if not */
3124 if (sii->pub.buscoretype == PCIE2_CORE_ID) {
3125 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE2_CORE_ID, 0);
3126 ASSERT(pcieregs != NULL);
3127 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
3128 } else if (sii->pub.buscoretype == PCIE_CORE_ID) {
3129 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0);
3130 ASSERT(pcieregs != NULL);
3131 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
3132 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
3133 pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
3134 ASSERT(pciregs != NULL);
3135 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
3137 pciidx = si_coreidx(&sii->pub);
3139 if (!reg16) return -1;
3141 val16 = R_REG(sii->osh, reg16);
3142 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
3143 val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
3144 W_REG(sii->osh, reg16, val16);
3147 /* restore the original index */
3148 si_setcoreidx(&sii->pub, origidx);
3150 pcicore_hwup(sii->pch);
3151 return 0;
3154 #if defined(BCMDBG)
3155 #endif
3157 /* change logical "focus" to the gpio core for optimized access */
3158 void *
3159 si_gpiosetcore(si_t *sih)
3161 return (si_setcoreidx(sih, SI_CC_IDX));
3165 * mask & set gpiocontrol bits.
3166 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
3167 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
3168 * to some chip-specific purpose.
3170 uint32
3171 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3173 uint regoff;
3175 regoff = 0;
3177 /* gpios could be shared on router platforms
3178 * ignore reservation if it's high priority (e.g., test apps)
3180 if ((priority != GPIO_HI_PRIORITY) &&
3181 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3182 mask = priority ? (si_gpioreservation & mask) :
3183 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3184 val &= mask;
3187 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
3188 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3191 /* mask&set gpio output enable bits */
3192 uint32
3193 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3195 uint regoff;
3197 regoff = 0;
3199 /* gpios could be shared on router platforms
3200 * ignore reservation if it's high priority (e.g., test apps)
3202 if ((priority != GPIO_HI_PRIORITY) &&
3203 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3204 mask = priority ? (si_gpioreservation & mask) :
3205 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3206 val &= mask;
3209 regoff = OFFSETOF(chipcregs_t, gpioouten);
3210 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3213 /* mask&set gpio output bits */
3214 uint32
3215 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3217 uint regoff;
3219 regoff = 0;
3221 /* gpios could be shared on router platforms
3222 * ignore reservation if it's high priority (e.g., test apps)
3224 if ((priority != GPIO_HI_PRIORITY) &&
3225 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3226 mask = priority ? (si_gpioreservation & mask) :
3227 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3228 val &= mask;
3231 regoff = OFFSETOF(chipcregs_t, gpioout);
3232 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3235 /* reserve one gpio */
3236 uint32
3237 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3239 /* only cores on SI_BUS share GPIO's and only applcation users need to
3240 * reserve/release GPIO
3242 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3243 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3244 return 0xffffffff;
3246 /* make sure only one bit is set */
3247 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3248 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3249 return 0xffffffff;
3252 /* already reserved */
3253 if (si_gpioreservation & gpio_bitmask)
3254 return 0xffffffff;
3255 /* set reservation */
3256 si_gpioreservation |= gpio_bitmask;
3258 return si_gpioreservation;
3261 /* release one gpio */
3263 * releasing the gpio doesn't change the current value on the GPIO last write value
3264 * persists till some one overwrites it
3267 uint32
3268 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3270 /* only cores on SI_BUS share GPIO's and only applcation users need to
3271 * reserve/release GPIO
3273 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3274 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3275 return 0xffffffff;
3277 /* make sure only one bit is set */
3278 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3279 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3280 return 0xffffffff;
3283 /* already released */
3284 if (!(si_gpioreservation & gpio_bitmask))
3285 return 0xffffffff;
3287 /* clear reservation */
3288 si_gpioreservation &= ~gpio_bitmask;
3290 return si_gpioreservation;
3293 /* return the current gpioin register value */
3294 uint32
3295 si_gpioin(si_t *sih)
3297 uint regoff;
3299 regoff = OFFSETOF(chipcregs_t, gpioin);
3300 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
3303 /* mask&set gpio interrupt polarity bits */
3304 uint32
3305 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3307 uint regoff;
3309 /* gpios could be shared on router platforms */
3310 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3311 mask = priority ? (si_gpioreservation & mask) :
3312 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3313 val &= mask;
3316 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
3317 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3320 /* mask&set gpio interrupt mask bits */
3321 uint32
3322 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3324 uint regoff;
3326 /* gpios could be shared on router platforms */
3327 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3328 mask = priority ? (si_gpioreservation & mask) :
3329 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3330 val &= mask;
3333 regoff = OFFSETOF(chipcregs_t, gpiointmask);
3334 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3337 /* assign the gpio to an led */
3338 uint32
3339 si_gpioled(si_t *sih, uint32 mask, uint32 val)
3341 if (sih->ccrev < 16)
3342 return 0xffffffff;
3344 /* gpio led powersave reg */
3345 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
3348 /* mask&set gpio timer val */
3349 uint32
3350 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
3352 if (sih->ccrev < 16)
3353 return 0xffffffff;
3355 return (si_corereg(sih, SI_CC_IDX,
3356 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
3359 uint32
3360 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
3362 uint offs;
3364 if (sih->ccrev < 20)
3365 return 0xffffffff;
3367 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
3368 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3371 uint32
3372 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
3374 uint offs;
3376 if (sih->ccrev < 11)
3377 return 0xffffffff;
3379 if (regtype == GPIO_REGEVT)
3380 offs = OFFSETOF(chipcregs_t, gpioevent);
3381 else if (regtype == GPIO_REGEVT_INTMSK)
3382 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
3383 else if (regtype == GPIO_REGEVT_INTPOL)
3384 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
3385 else
3386 return 0xffffffff;
3388 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3391 void *
3392 BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event,
3393 bool level, gpio_handler_t cb, void *arg)
3395 si_info_t *sii;
3396 gpioh_item_t *gi;
3398 ASSERT(event);
3399 ASSERT(cb != NULL);
3401 sii = SI_INFO(sih);
3402 if (sih->ccrev < 11)
3403 return NULL;
3405 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
3406 return NULL;
3408 bzero(gi, sizeof(gpioh_item_t));
3409 gi->event = event;
3410 gi->handler = cb;
3411 gi->arg = arg;
3412 gi->level = level;
3414 gi->next = sii->gpioh_head;
3415 sii->gpioh_head = gi;
3417 #ifdef BCMDBG_ERR
3419 gpioh_item_t *h = sii->gpioh_head;
3420 int cnt = 0;
3422 for (; h; h = h->next) {
3423 cnt++;
3424 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3425 h, h->handler, h->event));
3427 SI_ERROR(("gpiohdler total=%d\n", cnt));
3429 #endif
3430 return (void *)(gi);
3433 void
3434 BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh)
3436 si_info_t *sii;
3437 gpioh_item_t *p, *n;
3439 sii = SI_INFO(sih);
3440 if (sih->ccrev < 11)
3441 return;
3443 ASSERT(sii->gpioh_head != NULL);
3444 if ((void*)sii->gpioh_head == gpioh) {
3445 sii->gpioh_head = sii->gpioh_head->next;
3446 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3447 return;
3448 } else {
3449 p = sii->gpioh_head;
3450 n = p->next;
3451 while (n) {
3452 if ((void*)n == gpioh) {
3453 p->next = n->next;
3454 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3455 return;
3457 p = n;
3458 n = n->next;
3462 #ifdef BCMDBG_ERR
3464 gpioh_item_t *h = sii->gpioh_head;
3465 int cnt = 0;
3467 for (; h; h = h->next) {
3468 cnt++;
3469 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3470 h, h->handler, h->event));
3472 SI_ERROR(("gpiohdler total=%d\n", cnt));
3474 #endif
3475 ASSERT(0); /* Not found in list */
3478 void
3479 si_gpio_handler_process(si_t *sih)
3481 si_info_t *sii;
3482 gpioh_item_t *h;
3483 uint32 level = si_gpioin(sih);
3484 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
3485 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
3486 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
3488 sii = SI_INFO(sih);
3489 for (h = sii->gpioh_head; h != NULL; h = h->next) {
3490 if (h->handler) {
3491 uint32 status = (h->level ? level : edge) & h->event;
3492 uint32 polarity = (h->level ? levelp : edgep) & h->event;
3494 /* polarity bitval is opposite of status bitval */
3495 if (status ^ polarity)
3496 h->handler(status, h->arg);
3500 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
3503 uint32
3504 si_gpio_int_enable(si_t *sih, bool enable)
3506 uint offs;
3508 if (sih->ccrev < 11)
3509 return 0xffffffff;
3511 offs = OFFSETOF(chipcregs_t, intmask);
3512 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
3516 /* Return the size of the specified SOCRAM bank */
3517 static uint
3518 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
3520 uint banksize, bankinfo;
3521 uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3523 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
3525 W_REG(sii->osh, &regs->bankidx, bankidx);
3526 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3527 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
3528 return banksize;
3531 void
3532 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
3534 si_info_t *sii;
3535 uint origidx;
3536 uint intr_val = 0;
3537 sbsocramregs_t *regs;
3538 bool wasup;
3539 uint corerev;
3541 sii = SI_INFO(sih);
3543 /* Block ints and save current core */
3544 INTR_OFF(sii, intr_val);
3545 origidx = si_coreidx(sih);
3547 if (!set)
3548 *enable = *protect = *remap = 0;
3550 /* Switch to SOCRAM core */
3551 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3552 goto done;
3554 /* Get info for determining size */
3555 if (!(wasup = si_iscoreup(sih)))
3556 si_core_reset(sih, 0, 0);
3558 corerev = si_corerev(sih);
3559 if (corerev >= 10) {
3560 uint32 extcinfo;
3561 uint8 nb;
3562 uint8 i;
3563 uint32 bankidx, bankinfo;
3565 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3566 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3567 for (i = 0; i < nb; i++) {
3568 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3569 W_REG(sii->osh, &regs->bankidx, bankidx);
3570 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3571 if (set) {
3572 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
3573 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
3574 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
3575 if (*enable) {
3576 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
3577 if (*protect)
3578 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
3579 if ((corerev >= 16) && *remap)
3580 bankinfo |=
3581 (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
3583 W_REG(sii->osh, &regs->bankinfo, bankinfo);
3585 else if (i == 0) {
3586 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
3587 *enable = 1;
3588 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
3589 *protect = 1;
3590 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
3591 *remap = 1;
3597 /* Return to previous state and core */
3598 if (!wasup)
3599 si_core_disable(sih, 0);
3600 si_setcoreidx(sih, origidx);
3602 done:
3603 INTR_RESTORE(sii, intr_val);
3606 bool
3607 si_socdevram_remap_isenb(si_t *sih)
3609 si_info_t *sii;
3610 uint origidx;
3611 uint intr_val = 0;
3612 sbsocramregs_t *regs;
3613 bool wasup, remap = FALSE;
3614 uint corerev;
3615 uint32 extcinfo;
3616 uint8 nb;
3617 uint8 i;
3618 uint32 bankidx, bankinfo;
3620 sii = SI_INFO(sih);
3622 /* Block ints and save current core */
3623 INTR_OFF(sii, intr_val);
3624 origidx = si_coreidx(sih);
3626 /* Switch to SOCRAM core */
3627 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3628 goto done;
3630 /* Get info for determining size */
3631 if (!(wasup = si_iscoreup(sih)))
3632 si_core_reset(sih, 0, 0);
3634 corerev = si_corerev(sih);
3635 if (corerev >= 16) {
3636 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3637 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3638 for (i = 0; i < nb; i++) {
3639 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3640 W_REG(sii->osh, &regs->bankidx, bankidx);
3641 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3642 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
3643 remap = TRUE;
3644 break;
3649 /* Return to previous state and core */
3650 if (!wasup)
3651 si_core_disable(sih, 0);
3652 si_setcoreidx(sih, origidx);
3654 done:
3655 INTR_RESTORE(sii, intr_val);
3656 return remap;
3659 bool
3660 si_socdevram_pkg(si_t *sih)
3662 if (si_socdevram_size(sih) > 0)
3663 return TRUE;
3664 else
3665 return FALSE;
3668 uint32
3669 si_socdevram_size(si_t *sih)
3671 si_info_t *sii;
3672 uint origidx;
3673 uint intr_val = 0;
3674 uint32 memsize = 0;
3675 sbsocramregs_t *regs;
3676 bool wasup;
3677 uint corerev;
3679 sii = SI_INFO(sih);
3681 /* Block ints and save current core */
3682 INTR_OFF(sii, intr_val);
3683 origidx = si_coreidx(sih);
3685 /* Switch to SOCRAM core */
3686 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3687 goto done;
3689 /* Get info for determining size */
3690 if (!(wasup = si_iscoreup(sih)))
3691 si_core_reset(sih, 0, 0);
3693 corerev = si_corerev(sih);
3694 if (corerev >= 10) {
3695 uint32 extcinfo;
3696 uint8 nb;
3697 uint8 i;
3699 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3700 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3701 for (i = 0; i < nb; i++)
3702 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3705 /* Return to previous state and core */
3706 if (!wasup)
3707 si_core_disable(sih, 0);
3708 si_setcoreidx(sih, origidx);
3710 done:
3711 INTR_RESTORE(sii, intr_val);
3713 return memsize;
3716 uint32
3717 si_socdevram_remap_size(si_t *sih)
3719 si_info_t *sii;
3720 uint origidx;
3721 uint intr_val = 0;
3722 uint32 memsize = 0, banksz;
3723 sbsocramregs_t *regs;
3724 bool wasup;
3725 uint corerev;
3726 uint32 extcinfo;
3727 uint8 nb;
3728 uint8 i;
3729 uint32 bankidx, bankinfo;
3731 sii = SI_INFO(sih);
3733 /* Block ints and save current core */
3734 INTR_OFF(sii, intr_val);
3735 origidx = si_coreidx(sih);
3737 /* Switch to SOCRAM core */
3738 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3739 goto done;
3741 /* Get info for determining size */
3742 if (!(wasup = si_iscoreup(sih)))
3743 si_core_reset(sih, 0, 0);
3745 corerev = si_corerev(sih);
3746 if (corerev >= 16) {
3747 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3748 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3751 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
3752 * Only four banks are accessible to ARM
3754 if ((corerev == 16) && (nb == 5))
3755 nb = 4;
3757 for (i = 0; i < nb; i++) {
3758 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3759 W_REG(sii->osh, &regs->bankidx, bankidx);
3760 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3761 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
3762 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3763 memsize += banksz;
3764 } else {
3765 /* Account only consecutive banks for now */
3766 break;
3771 /* Return to previous state and core */
3772 if (!wasup)
3773 si_core_disable(sih, 0);
3774 si_setcoreidx(sih, origidx);
3776 done:
3777 INTR_RESTORE(sii, intr_val);
3779 return memsize;
3782 /* Return the RAM size of the SOCRAM core */
3783 uint32
3784 si_socram_size(si_t *sih)
3786 si_info_t *sii;
3787 uint origidx;
3788 uint intr_val = 0;
3790 sbsocramregs_t *regs;
3791 bool wasup;
3792 uint corerev;
3793 uint32 coreinfo;
3794 uint memsize = 0;
3796 sii = SI_INFO(sih);
3798 /* Block ints and save current core */
3799 INTR_OFF(sii, intr_val);
3800 origidx = si_coreidx(sih);
3802 /* Switch to SOCRAM core */
3803 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3804 goto done;
3806 /* Get info for determining size */
3807 if (!(wasup = si_iscoreup(sih)))
3808 si_core_reset(sih, 0, 0);
3809 corerev = si_corerev(sih);
3810 coreinfo = R_REG(sii->osh, &regs->coreinfo);
3812 /* Calculate size from coreinfo based on rev */
3813 if (corerev == 0)
3814 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
3815 else if (corerev < 3) {
3816 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
3817 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3818 } else if ((corerev <= 7) || (corerev == 12)) {
3819 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3820 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
3821 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
3822 if (lss != 0)
3823 nb --;
3824 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
3825 if (lss != 0)
3826 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
3827 } else {
3828 uint8 i;
3829 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3830 for (i = 0; i < nb; i++)
3831 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
3834 /* Return to previous state and core */
3835 if (!wasup)
3836 si_core_disable(sih, 0);
3837 si_setcoreidx(sih, origidx);
3839 done:
3840 INTR_RESTORE(sii, intr_val);
3842 return memsize;
3845 #if defined(WLOFFLD)
3847 /* Return the TCM-RAM size of the ARMCR4 core. */
3848 uint32
3849 si_tcm_size(si_t *sih)
3851 si_info_t *sii;
3852 uint origidx;
3853 uint intr_val = 0;
3854 uint8 *regs;
3855 bool wasup;
3856 uint32 corecap;
3857 uint memsize = 0;
3858 uint32 nab = 0;
3859 uint32 nbb = 0;
3860 uint32 totb = 0;
3861 uint32 bxinfo = 0;
3862 uint32 idx = 0;
3863 uint32 *arm_cap_reg;
3864 uint32 *arm_bidx;
3865 uint32 *arm_binfo;
3867 sii = SI_INFO(sih);
3869 /* Block ints and save current core */
3870 INTR_OFF(sii, intr_val);
3871 origidx = si_coreidx(sih);
3873 /* Switch to CR4 core */
3874 if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
3875 goto done;
3877 /* Get info for determining size. If in reset, come out of reset,
3878 * but remain in halt
3880 if (!(wasup = si_iscoreup(sih)))
3881 si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
3883 arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP);
3884 corecap = R_REG(sii->osh, arm_cap_reg);
3886 nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
3887 nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
3888 totb = nab + nbb;
3890 arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX);
3891 arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO);
3892 for (idx = 0; idx < totb; idx++) {
3893 W_REG(sii->osh, arm_bidx, idx);
3895 bxinfo = R_REG(sii->osh, arm_binfo);
3896 memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
3899 /* Return to previous state and core */
3900 if (!wasup)
3901 si_core_disable(sih, 0);
3902 si_setcoreidx(sih, origidx);
3904 done:
3905 INTR_RESTORE(sii, intr_val);
3907 return memsize;
3909 #endif
3911 #ifdef BCMECICOEX
3912 #define NOTIFY_BT_FM_DISABLE(sih, val) \
3913 si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
3914 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
3916 /* Query OTP to see if FM is disabled */
3917 static int
3918 BCMINITFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled)
3920 int error = BCME_OK;
3921 uint bitoff = 0;
3922 bool wasup;
3923 void *oh;
3925 /* Determine the bit for the chip */
3926 switch (CHIPID(sih->chip)) {
3927 case BCM4325_CHIP_ID:
3928 if (CHIPREV(sih->chiprev) >= 6)
3929 bitoff = OTP4325_FM_DISABLED_OFFSET;
3930 break;
3931 default:
3932 break;
3935 /* If there is a bit for this chip, check it */
3936 if (bitoff) {
3937 if (!(wasup = si_is_otp_powered(sih))) {
3938 si_otp_power(sih, TRUE);
3941 if ((oh = otp_init(sih)) != NULL)
3942 *FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET);
3943 else
3944 error = BCME_NOTFOUND;
3946 if (!wasup) {
3947 si_otp_power(sih, FALSE);
3951 return error;
3954 bool
3955 si_eci(si_t *sih)
3957 return (!!(sih->cccaps & CC_CAP_ECI));
3960 bool
3961 si_seci(si_t *sih)
3963 return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT);
3966 /* ECI Init routine */
3968 BCMINITFN(si_eci_init)(si_t *sih)
3970 uint32 origidx = 0;
3971 si_info_t *sii;
3972 chipcregs_t *cc;
3973 bool fast;
3974 uint16 FMDisabled = FALSE;
3976 /* check for ECI capability */
3977 if (!(sih->cccaps & CC_CAP_ECI))
3978 return BCME_ERROR;
3980 sii = SI_INFO(sih);
3981 fast = SI_FAST(sii);
3982 if (!fast) {
3983 origidx = sii->curidx;
3984 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3985 return BCME_ERROR;
3986 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3987 return BCME_ERROR;
3988 ASSERT(cc);
3990 /* disable level based interrupts */
3991 if (sih->ccrev < 35) {
3992 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0);
3993 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0);
3994 W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0);
3996 else {
3997 W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0);
3998 W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0);
4001 /* Assign eci_output bits between 'wl' and dot11mac */
4002 if (sih->ccrev < 35) {
4003 W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS);
4005 else {
4006 W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS);
4007 W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS);
4010 /* enable only edge based interrupts
4011 * only toggle on bit 62 triggers an interrupt
4013 if (sih->ccrev < 35) {
4014 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0);
4015 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0);
4016 W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0);
4018 else {
4019 W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0);
4020 W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0);
4023 /* restore previous core */
4024 if (!fast)
4025 si_setcoreidx(sih, origidx);
4027 /* if FM disabled in OTP, let BT know */
4028 if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) {
4029 if (FMDisabled) {
4030 NOTIFY_BT_FM_DISABLE(sih, 1);
4034 return 0;
4038 * Write values to BT on eci_output.
4040 void
4041 si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt)
4043 uint32 offset;
4045 /* Nothing to do if there is no eci or seci */
4046 if (((sih->cccaps & CC_CAP_ECI) == 0) && ((sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT) == 0))
4047 return;
4049 /* Clear interrupt bit by default */
4050 if (interrupt)
4051 si_corereg(sih, SI_CC_IDX,
4052 (sih->ccrev < 35 ?
4053 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
4054 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
4055 (1 << 30), 0);
4057 if (sih->ccrev >= 35) {
4058 if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
4059 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi);
4060 mask = mask & ~0xFFFF0000;
4062 else {
4063 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo);
4064 mask = mask | (1<<30);
4065 val = val & ~(1 << 30);
4068 else {
4069 offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output);
4070 val = val & ~(1 << 30);
4073 si_corereg(sih, SI_CC_IDX, offset, mask, val);
4075 /* Set interrupt bit if needed */
4076 if (interrupt)
4077 si_corereg(sih, SI_CC_IDX,
4078 (sih->ccrev < 35 ?
4079 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
4080 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
4081 (1 << 30), (1 << 30));
4084 /* seci clock enable/disable */
4085 static void
4086 si_seci_clkreq(si_t *sih, bool enable)
4088 uint32 clk_ctl_st;
4089 uint32 offset;
4090 uint32 val;
4092 if (!si_seci(sih))
4093 return;
4095 if (enable)
4096 val = CLKCTL_STS_SECI_CLK_REQ;
4097 else
4098 val = 0;
4100 offset = OFFSETOF(chipcregs_t, clk_ctl_st);
4102 si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val);
4104 if (!enable)
4105 return;
4107 SPINWAIT(!(si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL),
4108 PMU_MAX_TRANSITION_DLY);
4110 clk_ctl_st = si_corereg(sih, 0, offset, 0, 0);
4111 if (enable) {
4112 if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) {
4113 SI_ERROR(("SECI clock is still not available\n"));
4114 return;
4119 void
4120 BCMINITFN(si_seci_down)(si_t *sih)
4122 uint32 origidx = 0;
4123 si_info_t *sii;
4124 chipcregs_t *cc;
4125 bool fast;
4126 uint32 seci_conf;
4128 if (!si_seci(sih))
4129 return;
4131 sii = SI_INFO(sih);
4132 fast = SI_FAST(sii);
4134 if (!fast) {
4135 origidx = sii->curidx;
4136 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4137 return;
4138 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
4139 return;
4140 ASSERT(cc);
4141 /* 4331 X28 sign off seci */
4142 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4143 /* flush seci */
4144 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4145 seci_conf |= SECI_UPD_SECI;
4146 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4147 SPINWAIT((R_REG(sii->osh, &cc->SECI_config) & SECI_UPD_SECI), 1000);
4149 /* SECI sign off */
4150 W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_0);
4151 W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_1);
4152 SPINWAIT((R_REG(sii->osh, &cc->seci_uart_lsr) & (1 << 2)), 1000);
4153 /* put seci in reset */
4154 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4155 seci_conf &= ~SECI_ENAB_SECI_ECI;
4156 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4157 seci_conf |= SECI_RESET;
4158 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4161 /* bring down the clock if up */
4162 si_seci_clkreq(sih, FALSE);
4164 /* restore previous core */
4165 if (!fast)
4166 si_setcoreidx(sih, origidx);
4169 void
4170 si_seci_upd(si_t *sih, bool enable)
4172 uint32 origidx = 0;
4173 si_info_t *sii;
4174 chipcregs_t *cc;
4175 bool fast;
4176 uint32 regval;
4177 uint intr_val = 0;
4179 if (!si_seci(sih))
4180 return;
4182 sii = SI_INFO(sih);
4183 fast = SI_FAST(sii);
4184 INTR_OFF(sii, intr_val);
4185 if (!fast) {
4186 origidx = sii->curidx;
4187 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4188 goto exit;
4189 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
4190 goto exit;
4192 ASSERT(cc);
4194 /* 4331 Select SECI based on enable input */
4195 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4196 regval = R_REG(sii->osh, &cc->chipcontrol);
4197 if (enable)
4198 regval |= CCTRL4331_SECI;
4199 else
4200 regval &= ~CCTRL4331_SECI;
4201 W_REG(sii->osh, &cc->chipcontrol, regval);
4203 exit:
4204 /* restore previous core */
4205 if (!fast)
4206 si_setcoreidx(sih, origidx);
4208 INTR_RESTORE(sii, intr_val);
4211 /* SECI Init routine, pass in seci_mode */
4212 void *
4213 BCMINITFN(si_seci_init)(si_t *sih, uint8 seci_mode)
4215 uint32 origidx = 0;
4216 uint32 offset;
4217 si_info_t *sii;
4218 void *ptr;
4219 chipcregs_t *cc;
4220 bool fast;
4221 uint32 seci_conf;
4222 uint32 regval;
4224 if (sih->ccrev < 35)
4225 return NULL;
4227 if (!si_seci(sih))
4228 return NULL;
4230 if (seci_mode > SECI_MODE_MASK)
4231 return NULL;
4233 sii = SI_INFO(sih);
4234 fast = SI_FAST(sii);
4235 if (!fast) {
4236 origidx = sii->curidx;
4237 if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4238 return NULL;
4239 } else if ((ptr = CCREGS_FAST(sii)) == NULL)
4240 return NULL;
4241 cc = (chipcregs_t *)ptr;
4242 ASSERT(cc);
4245 /* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
4246 if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
4247 CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4248 regval = R_REG(sii->osh, &cc->chipcontrol);
4249 regval |= CCTRL4331_SECI;
4250 W_REG(sii->osh, &cc->chipcontrol, regval);
4253 /* 43143 (ccrev 43) mux SECI on JTAG pins. Select SECI. */
4254 if (CHIPID(sih->chip) == BCM43143_CHIP_ID) {
4255 regval = R_REG(sii->osh, &cc->chipcontrol);
4256 regval &= ~(CCTRL_43143_SECI | CCTRL_43143_BT_LEGACY);
4257 switch (seci_mode) {
4258 case SECI_MODE_LEGACY_3WIRE_WLAN:
4259 regval |= CCTRL_43143_BT_LEGACY;
4260 break;
4261 case SECI_MODE_SECI:
4262 regval |= CCTRL_43143_SECI;
4263 break;
4264 default:
4265 ASSERT(0);
4267 W_REG(sii->osh, &cc->chipcontrol, regval);
4270 if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
4271 (CHIPID(sih->chip) == BCM43143_CHIP_ID)) {
4272 regval = R_REG(sii->osh, &cc->jtagctrl);
4273 regval |= 0x1;
4274 W_REG(sii->osh, &cc->jtagctrl, regval);
4277 /* enable SECI clock */
4278 si_seci_clkreq(sih, TRUE);
4280 /* put the SECI in reset */
4281 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4282 seci_conf &= ~SECI_ENAB_SECI_ECI;
4283 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4284 seci_conf = SECI_RESET;
4285 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4287 /* set force-low, and set EN_SECI for all non-legacy modes */
4288 seci_conf |= SECI_ENAB_SECIOUT_DIS;
4289 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
4290 (seci_mode == SECI_MODE_HALF_SECI))
4292 seci_conf |= SECI_ENAB_SECI_ECI;
4294 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4296 /* take seci out of reset */
4297 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4298 seci_conf &= ~(SECI_RESET);
4299 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4301 /* set UART/SECI baud rate */
4302 /* hard-coded at 4MBaud for now */
4303 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
4304 (seci_mode == SECI_MODE_HALF_SECI)) {
4305 if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
4306 (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
4307 (CHIPID(sih->chip) == BCM43143_CHIP_ID)) {
4308 /* 43236 ccrev = 36 and MAC clk = 96MHz */
4309 /* 4331,43143 MAC clk = 96MHz */
4310 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
4311 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF);
4312 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
4313 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
4315 else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4316 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
4317 /* MAC clk is 160MHz */
4318 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
4319 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFE);
4320 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
4321 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
4323 else {
4324 /* 4336 MAC clk is 80MHz */
4325 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
4326 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF);
4327 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
4328 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22);
4331 /* LCR/MCR settings */
4332 offset = OFFSETOF(chipcregs_t, seci_uart_lcr);
4333 si_corereg(sih, SI_CC_IDX, offset, 0xFF,
4334 (SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */
4335 offset = OFFSETOF(chipcregs_t, seci_uart_mcr);
4336 si_corereg(sih, SI_CC_IDX, offset,
4337 0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */
4339 /* Give control of ECI output regs to MAC core */
4340 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo);
4341 si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS);
4342 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi);
4343 si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS);
4346 /* set the seci mode in seci conf register */
4347 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4348 seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT);
4349 seci_conf |= (seci_mode << SECI_MODE_SHIFT);
4350 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4352 /* Clear force-low bit */
4353 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4354 seci_conf &= ~SECI_ENAB_SECIOUT_DIS;
4355 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4357 /* restore previous core */
4358 if (!fast)
4359 si_setcoreidx(sih, origidx);
4361 return ptr;
4363 #endif /* BCMECICOEX */
4365 #if !defined(_CFE_) || defined(CFG_WL)
4366 void
4367 si_btcgpiowar(si_t *sih)
4369 si_info_t *sii;
4370 uint origidx;
4371 uint intr_val = 0;
4372 chipcregs_t *cc;
4374 sii = SI_INFO(sih);
4376 /* Make sure that there is ChipCommon core present &&
4377 * UART_TX is strapped to 1
4379 if (!(sih->cccaps & CC_CAP_UARTGPIO))
4380 return;
4382 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
4383 INTR_OFF(sii, intr_val);
4385 origidx = si_coreidx(sih);
4387 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4388 ASSERT(cc != NULL);
4390 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
4392 /* restore the original index */
4393 si_setcoreidx(sih, origidx);
4395 INTR_RESTORE(sii, intr_val);
4398 void
4399 si_chipcontrl_btshd0_4331(si_t *sih, bool on)
4401 si_info_t *sii;
4402 chipcregs_t *cc;
4403 uint origidx;
4404 uint32 val;
4405 uint intr_val = 0;
4407 sii = SI_INFO(sih);
4409 INTR_OFF(sii, intr_val);
4411 origidx = si_coreidx(sih);
4413 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4415 val = R_REG(sii->osh, &cc->chipcontrol);
4417 /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
4418 if (on) {
4419 /* Enable bt_shd0 on gpio4: */
4420 val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
4421 W_REG(sii->osh, &cc->chipcontrol, val);
4422 } else {
4423 val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
4424 W_REG(sii->osh, &cc->chipcontrol, val);
4427 /* restore the original index */
4428 si_setcoreidx(sih, origidx);
4430 INTR_RESTORE(sii, intr_val);
4433 void
4434 si_chipcontrl_restore(si_t *sih, uint32 val)
4436 si_info_t *sii;
4437 chipcregs_t *cc;
4438 uint origidx;
4440 sii = SI_INFO(sih);
4441 origidx = si_coreidx(sih);
4442 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4443 W_REG(sii->osh, &cc->chipcontrol, val);
4444 si_setcoreidx(sih, origidx);
4447 uint32
4448 si_chipcontrl_read(si_t *sih)
4450 si_info_t *sii;
4451 chipcregs_t *cc;
4452 uint origidx;
4453 uint32 val;
4455 sii = SI_INFO(sih);
4456 origidx = si_coreidx(sih);
4457 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4458 val = R_REG(sii->osh, &cc->chipcontrol);
4459 si_setcoreidx(sih, origidx);
4460 return val;
4463 void
4464 si_chipcontrl_epa4331(si_t *sih, bool on)
4466 si_info_t *sii;
4467 chipcregs_t *cc;
4468 uint origidx;
4469 uint32 val;
4471 sii = SI_INFO(sih);
4472 origidx = si_coreidx(sih);
4474 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4476 val = R_REG(sii->osh, &cc->chipcontrol);
4478 if (on) {
4479 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
4480 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
4481 /* Ext PA Controls for 4331 12x9 Package */
4482 W_REG(sii->osh, &cc->chipcontrol, val);
4483 } else {
4484 /* Ext PA Controls for 4331 12x12 Package */
4485 if (sih->chiprev > 0) {
4486 W_REG(sii->osh, &cc->chipcontrol, val |
4487 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
4488 } else {
4489 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
4492 } else {
4493 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
4494 W_REG(sii->osh, &cc->chipcontrol, val);
4497 si_setcoreidx(sih, origidx);
4500 /* switch muxed pins, on: SROM, off: FEMCTRL */
4501 void
4502 si_chipcontrl_srom4360(si_t *sih, bool on)
4504 si_info_t *sii;
4505 chipcregs_t *cc;
4506 uint origidx;
4507 uint32 val;
4509 sii = SI_INFO(sih);
4510 origidx = si_coreidx(sih);
4512 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4514 val = R_REG(sii->osh, &cc->chipcontrol);
4516 if (on) {
4517 val &= ~(CCTRL4360_SECI_MODE |
4518 CCTRL4360_BTSWCTRL_MODE |
4519 CCTRL4360_EXTRA_FEMCTRL_MODE |
4520 CCTRL4360_BT_LGCY_MODE |
4521 CCTRL4360_CORE2FEMCTRL4_ON);
4523 W_REG(sii->osh, &cc->chipcontrol, val);
4524 } else {
4527 si_setcoreidx(sih, origidx);
4530 void
4531 si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
4533 si_info_t *sii;
4534 chipcregs_t *cc;
4535 uint origidx;
4536 uint32 val;
4537 bool sel_chip;
4539 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
4540 (CHIPID(sih->chip) == BCM43431_CHIP_ID);
4541 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
4543 if (!sel_chip)
4544 return;
4546 sii = SI_INFO(sih);
4547 origidx = si_coreidx(sih);
4549 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4551 val = R_REG(sii->osh, &cc->chipcontrol);
4553 if (enter_wowl) {
4554 val |= CCTRL4331_EXTPA_EN;
4555 W_REG(sii->osh, &cc->chipcontrol, val);
4556 } else {
4557 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
4558 W_REG(sii->osh, &cc->chipcontrol, val);
4560 si_setcoreidx(sih, origidx);
4562 #endif /* !_CFE_ || CFG_WL */
4564 uint
4565 si_pll_reset(si_t *sih)
4567 uint err = 0;
4569 uint intr_val = 0;
4570 si_info_t *sii;
4571 sii = SI_INFO(sih);
4572 INTR_OFF(sii, intr_val);
4573 err = si_pll_minresmask_reset(sih, sii->osh);
4574 INTR_RESTORE(sii, intr_val);
4575 return (err);
4578 /* Enable BT-COEX & Ex-PA for 4313 */
4579 void
4580 si_epa_4313war(si_t *sih)
4582 si_info_t *sii;
4583 chipcregs_t *cc;
4584 uint origidx;
4586 sii = SI_INFO(sih);
4587 origidx = si_coreidx(sih);
4589 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4591 /* EPA Fix */
4592 W_REG(sii->osh, &cc->gpiocontrol,
4593 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
4595 si_setcoreidx(sih, origidx);
4598 void
4599 si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
4601 si_info_t *sii;
4602 sii = SI_INFO(sih);
4604 si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear);
4607 /* WL/BT control for 4313 btcombo boards >= P250 */
4608 void
4609 si_btcombo_p250_4313_war(si_t *sih)
4611 si_info_t *sii;
4612 chipcregs_t *cc;
4613 uint origidx;
4615 sii = SI_INFO(sih);
4616 origidx = si_coreidx(sih);
4618 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4619 W_REG(sii->osh, &cc->gpiocontrol,
4620 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
4622 W_REG(sii->osh, &cc->gpioouten,
4623 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
4625 si_setcoreidx(sih, origidx);
4627 void
4628 si_btc_enable_chipcontrol(si_t *sih)
4630 si_info_t *sii;
4631 chipcregs_t *cc;
4632 uint origidx;
4634 sii = SI_INFO(sih);
4635 origidx = si_coreidx(sih);
4637 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4639 /* BT fix */
4640 W_REG(sii->osh, &cc->chipcontrol,
4641 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
4643 si_setcoreidx(sih, origidx);
4645 void
4646 si_btcombo_43228_war(si_t *sih)
4648 si_info_t *sii;
4649 chipcregs_t *cc;
4650 uint origidx;
4652 sii = SI_INFO(sih);
4653 origidx = si_coreidx(sih);
4655 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4657 W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
4658 W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
4660 si_setcoreidx(sih, origidx);
4663 /* check if the device is removed */
4664 bool
4665 si_deviceremoved(si_t *sih)
4667 uint32 w;
4668 si_info_t *sii;
4670 sii = SI_INFO(sih);
4672 switch (BUSTYPE(sih->bustype)) {
4673 case PCI_BUS:
4674 ASSERT(sii->osh != NULL);
4675 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
4676 if ((w & 0xFFFF) != VENDOR_BROADCOM)
4677 return TRUE;
4678 break;
4680 return FALSE;
4683 bool
4684 si_is_sprom_available(si_t *sih)
4686 if (sih->ccrev >= 31) {
4687 si_info_t *sii;
4688 uint origidx;
4689 chipcregs_t *cc;
4690 uint32 sromctrl;
4692 if ((sih->cccaps & CC_CAP_SROM) == 0)
4693 return FALSE;
4695 sii = SI_INFO(sih);
4696 origidx = sii->curidx;
4697 cc = si_setcoreidx(sih, SI_CC_IDX);
4698 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
4699 si_setcoreidx(sih, origidx);
4700 return (sromctrl & SRC_PRESENT);
4703 switch (CHIPID(sih->chip)) {
4704 case BCM4312_CHIP_ID:
4705 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
4706 case BCM4325_CHIP_ID:
4707 return (sih->chipst & CST4325_SPROM_SEL) != 0;
4708 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4709 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
4710 case BCM4342_CHIP_ID: {
4711 uint32 spromotp;
4712 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4713 CST4322_SPROM_OTP_SEL_SHIFT;
4714 return (spromotp & CST4322_SPROM_PRESENT) != 0;
4716 case BCM4329_CHIP_ID:
4717 return (sih->chipst & CST4329_SPROM_SEL) != 0;
4718 case BCM4315_CHIP_ID:
4719 return (sih->chipst & CST4315_SPROM_SEL) != 0;
4720 case BCM4319_CHIP_ID:
4721 return (sih->chipst & CST4319_SPROM_SEL) != 0;
4722 case BCM4336_CHIP_ID:
4723 case BCM43362_CHIP_ID:
4724 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
4725 case BCM4330_CHIP_ID:
4726 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
4727 case BCM4313_CHIP_ID:
4728 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
4729 case BCM4331_CHIP_ID:
4730 case BCM43431_CHIP_ID:
4731 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
4732 case BCM43239_CHIP_ID:
4733 return ((sih->chipst & CST43239_SPROM_MASK) &&
4734 !(sih->chipst & CST43239_SFLASH_MASK));
4735 case BCM4324_CHIP_ID:
4736 case BCM43242_CHIP_ID:
4737 return ((sih->chipst & CST4324_SPROM_MASK) &&
4738 !(sih->chipst & CST4324_SFLASH_MASK));
4739 case BCM4335_CHIP_ID:
4740 return ((sih->chipst & CST4335_SPROM_MASK) &&
4741 !(sih->chipst & CST4335_SFLASH_MASK));
4742 case BCM43131_CHIP_ID:
4743 case BCM43217_CHIP_ID:
4744 case BCM43227_CHIP_ID:
4745 case BCM43228_CHIP_ID:
4746 case BCM43428_CHIP_ID:
4747 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
4748 default:
4749 return TRUE;
4753 bool
4754 si_is_otp_disabled(si_t *sih)
4756 switch (CHIPID(sih->chip)) {
4757 case BCM4325_CHIP_ID:
4758 return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN;
4759 case BCM4322_CHIP_ID:
4760 case BCM43221_CHIP_ID:
4761 case BCM43231_CHIP_ID:
4762 case BCM4342_CHIP_ID:
4763 return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4764 CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) !=
4765 CST4322_OTP_PRESENT;
4766 case BCM4329_CHIP_ID:
4767 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN;
4768 case BCM4315_CHIP_ID:
4769 return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN;
4770 case BCM4319_CHIP_ID:
4771 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN;
4772 case BCM4336_CHIP_ID:
4773 case BCM43362_CHIP_ID:
4774 return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
4775 case BCM4330_CHIP_ID:
4776 return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
4777 case BCM43237_CHIP_ID:
4778 return FALSE;
4779 case BCM4313_CHIP_ID:
4780 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
4781 case BCM4331_CHIP_ID:
4782 return (sih->chipst & CST4331_OTP_PRESENT) != CST4331_OTP_PRESENT;
4783 case BCM4360_CHIP_ID:
4784 case BCM43526_CHIP_ID:
4785 case BCM43460_CHIP_ID:
4786 case BCM4352_CHIP_ID:
4787 /* 4360 OTP is always powered and enabled */
4788 return FALSE;
4789 /* These chips always have their OTP on */
4790 case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: case BCM43222_CHIP_ID:
4791 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID:
4792 case BCM43421_CHIP_ID:
4793 case BCM43226_CHIP_ID:
4794 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4795 case BCM43234_CHIP_ID: case BCM43239_CHIP_ID: case BCM4324_CHIP_ID:
4796 case BCM43431_CHIP_ID:
4797 case BCM43131_CHIP_ID:
4798 case BCM43217_CHIP_ID:
4799 case BCM43227_CHIP_ID:
4800 case BCM43228_CHIP_ID:
4801 case BCM43428_CHIP_ID: case BCM4335_CHIP_ID:
4802 case BCM43143_CHIP_ID:
4803 case BCM43242_CHIP_ID:
4804 case BCM43243_CHIP_ID:
4805 default:
4806 return FALSE;
4810 bool
4811 si_is_otp_powered(si_t *sih)
4813 if (PMUCTL_ENAB(sih))
4814 return si_pmu_is_otp_powered(sih, si_osh(sih));
4815 return TRUE;
4818 void
4819 si_otp_power(si_t *sih, bool on)
4821 if (PMUCTL_ENAB(sih))
4822 si_pmu_otp_power(sih, si_osh(sih), on);
4823 OSL_DELAY(1000);
4826 bool
4827 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4828 si_is_sprom_enabled(si_t *sih)
4829 #else
4830 BCMATTACHFN(si_is_sprom_enabled)(si_t *sih)
4831 #endif
4833 if (PMUCTL_ENAB(sih))
4834 return si_pmu_is_sprom_enabled(sih, si_osh(sih));
4835 return TRUE;
4838 void
4839 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4840 si_sprom_enable(si_t *sih, bool enable)
4841 #else
4842 BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable)
4843 #endif
4845 if (PMUCTL_ENAB(sih))
4846 si_pmu_sprom_enable(sih, si_osh(sih), enable);
4849 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
4851 si_cis_source(si_t *sih)
4853 /* Many chips have the same mapping of their chipstatus field */
4854 static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
4855 static const uint cis_43236_sel[] = { CIS_DEFAULT, CIS_OTP };
4857 /* PCI chips use SROM format instead of CIS */
4858 if (BUSTYPE(sih->bustype) == PCI_BUS)
4859 return BCME_NOTFOUND;
4861 switch (CHIPID(sih->chip)) {
4862 case BCM4325_CHIP_ID:
4863 return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4864 CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)];
4865 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4866 case BCM4342_CHIP_ID: {
4867 uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4868 CST4322_SPROM_OTP_SEL_SHIFT;
4870 return ((strap >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[strap]);
4874 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4875 case BCM43234_CHIP_ID: {
4876 uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >>
4877 CST43236_OTP_SEL_SHIFT;
4878 return ((strap >= ARRAYSIZE(cis_43236_sel)) ? CIS_DEFAULT : cis_43236_sel[strap]);
4881 case BCM4329_CHIP_ID:
4882 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4883 CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)];
4885 case BCM4315_CHIP_ID:
4887 return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4888 CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)];
4890 case BCM4319_CHIP_ID: {
4891 uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >>
4892 CST4319_SPROM_OTP_SEL_SHIFT);
4893 return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319];
4895 case BCM4336_CHIP_ID:
4896 case BCM43362_CHIP_ID: {
4897 if (sih->chipst & CST4336_SPROM_PRESENT)
4898 return CIS_SROM;
4899 if (sih->chipst & CST4336_OTP_PRESENT)
4900 return CIS_OTP;
4901 return CIS_DEFAULT;
4903 case BCM4330_CHIP_ID: {
4904 if (sih->chipst & CST4330_SPROM_PRESENT)
4905 return CIS_SROM;
4906 if (sih->chipst & CST4330_OTP_PRESENT)
4907 return CIS_OTP;
4908 return CIS_DEFAULT;
4910 case BCM43239_CHIP_ID: {
4911 if ((sih->chipst & CST43239_SPROM_MASK) && !(sih->chipst & CST43239_SFLASH_MASK))
4912 return CIS_SROM;
4913 return CIS_OTP;
4915 case BCM4324_CHIP_ID:
4917 if ((sih->chipst & CST4324_SPROM_MASK) && !(sih->chipst & CST4324_SFLASH_MASK))
4918 return CIS_SROM;
4919 return CIS_OTP;
4921 case BCM4335_CHIP_ID:
4923 if ((sih->chipst & CST4335_SPROM_MASK) && !(sih->chipst & CST4335_SFLASH_MASK))
4924 return CIS_SROM;
4925 return CIS_OTP;
4927 case BCM43237_CHIP_ID: {
4928 uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >>
4929 CST43237_OTP_SEL_SHIFT;
4930 return ((strap >= ARRAYSIZE(cis_43236_sel)) ? CIS_DEFAULT : cis_43236_sel[strap]);
4932 case BCM43143_CHIP_ID: {
4933 return CIS_OTP; /* BCM43143 does not support SROM nor OTP strappings */
4935 case BCM43242_CHIP_ID:
4936 case BCM43243_CHIP_ID:
4938 return CIS_OTP; /* BCM43242 does not support SPROM */
4940 case BCM4360_CHIP_ID:
4941 case BCM4352_CHIP_ID:
4942 case BCM43526_CHIP_ID: {
4943 if ((sih->chipst & CST4360_OTP_ENABLED))
4944 return CIS_OTP;
4945 return CIS_DEFAULT;
4947 default:
4948 return CIS_DEFAULT;
4952 /* Read/write to OTP to find the FAB manf */
4954 BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw)
4956 int error = BCME_OK;
4957 uint offset = 0;
4958 uint16 data, mask = 0, shift = 0;
4960 switch (CHIPID(sih->chip)) {
4961 case BCM4329_CHIP_ID:
4962 /* Bit locations 133-130 */
4963 if (sih->chiprev >= 3) {
4964 offset = 8;
4965 mask = 0x3c;
4966 shift = 2;
4968 break;
4969 case BCM43362_CHIP_ID:
4970 /* Bit locations 134-130 */
4971 offset = 8;
4972 mask = 0x7c;
4973 shift = 2;
4974 break;
4975 case BCM5356_CHIP_ID:
4976 /* Bit locations 133-130 */
4977 offset = 8;
4978 mask = 0x3c;
4979 shift = 2;
4980 break;
4981 default:
4982 error = BCME_EPERM;
4983 return error;
4986 if (rw == TRUE) {
4987 /* TRUE --> read */
4988 error = otp_read_word(sih, offset, &data);
4989 if (!error)
4990 *fabid = (data & mask) >> shift;
4991 } else {
4992 data = *fabid;
4993 data = (data << shift) & mask;
4994 #ifdef BCMNVRAMW
4995 error = otp_write_word(sih, offset, data);
4996 #endif /* BCMNVRAMW */
4999 return error;
5001 uint16 BCMINITFN(si_fabid)(si_t *sih)
5003 uint32 data;
5004 uint16 fabid = 0;
5006 switch (CHIPID(sih->chip)) {
5007 case BCM4329_CHIP_ID:
5008 case BCM43362_CHIP_ID:
5009 case BCM5356_CHIP_ID:
5010 if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK)
5012 SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));
5014 break;
5016 case BCM4330_CHIP_ID:
5017 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
5018 0, 0);
5019 fabid = ((data & 0xc0000000) >> 30)+((data & 0x20000000) >> 27);
5020 break;
5022 case BCM4334_CHIP_ID:
5023 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid), 0, 0);
5024 fabid = data & 0xf;
5025 break;
5027 case BCM4324_CHIP_ID:
5028 case BCM4335_CHIP_ID:
5029 case BCM43143_CHIP_ID:
5030 case BCM43242_CHIP_ID:
5031 case BCM43243_CHIP_ID:
5032 /* intentional fallthrough */
5033 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid), 0, 0);
5034 fabid = data & 0xf;
5035 break;
5037 default:
5038 break;
5041 return fabid;
5044 uint32 si_get_sromctl(si_t *sih)
5046 chipcregs_t *cc;
5047 uint origidx;
5048 uint32 sromctl;
5049 osl_t *osh;
5051 osh = si_osh(sih);
5052 origidx = si_coreidx(sih);
5053 cc = si_setcoreidx(sih, SI_CC_IDX);
5054 ASSERT((uintptr)cc);
5056 sromctl = R_REG(osh, &cc->sromcontrol);
5058 /* return to the original core */
5059 si_setcoreidx(sih, origidx);
5060 return sromctl;
5063 int si_set_sromctl(si_t *sih, uint32 value)
5065 chipcregs_t *cc;
5066 uint origidx;
5067 osl_t *osh;
5069 osh = si_osh(sih);
5070 origidx = si_coreidx(sih);
5071 cc = si_setcoreidx(sih, SI_CC_IDX);
5072 ASSERT((uintptr)cc);
5074 /* get chipcommon rev */
5075 if (si_corerev(sih) < 32)
5076 return BCME_UNSUPPORTED;
5078 W_REG(osh, &cc->sromcontrol, value);
5080 /* return to the original core */
5081 si_setcoreidx(sih, origidx);
5082 return BCME_OK;