BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / shared / siutils.c
blobda6bb3141ce9937fc635155d1bc675e5b7c74857
1 /*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2011, 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 330112 2012-04-27 22:31:26Z $
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 static void si_sromvars_fixup_4331(si_t *sih, char *pvars);
61 /* dev path concatenation util */
62 static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
63 static bool _si_clkctl_cc(si_info_t *sii, uint mode);
64 static bool si_ispcie(si_info_t *sii);
65 static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype);
68 /* global variable to indicate reservation/release of gpio's */
69 static uint32 si_gpioreservation = 0;
71 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
73 int do_4360_pcie2_war = 0;
76 * Allocate a si handle.
77 * devid - pci device id (used to determine chip#)
78 * osh - opaque OS handle
79 * regs - virtual address of initial core registers
80 * bustype - pci/pcmcia/sb/sdio/etc
81 * vars - pointer to a pointer area for "environment" variables
82 * varsz - pointer to int to return the size of the vars
84 si_t *
85 BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs,
86 uint bustype, void *sdh, char **vars, uint *varsz)
88 si_info_t *sii;
90 /* alloc si_info_t */
91 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
92 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
93 return (NULL);
96 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
97 MFREE(osh, sii, sizeof(si_info_t));
98 return (NULL);
100 sii->vars = vars ? *vars : NULL;
101 sii->varsz = varsz ? *varsz : 0;
103 return (si_t *)sii;
106 /* global kernel resource */
107 static si_info_t ksii;
109 static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
111 /* generic kernel variant of si_attach() */
112 si_t *
113 BCMATTACHFN(si_kattach)(osl_t *osh)
115 static bool ksii_attached = FALSE;
117 if (!ksii_attached) {
118 void *regs;
119 #ifndef SI_ENUM_BASE_VARIABLE
120 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
121 #endif
123 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
124 SI_BUS, NULL,
125 osh != SI_OSH ? &ksii.vars : NULL,
126 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
127 SI_ERROR(("si_kattach: si_doattach failed\n"));
128 REG_UNMAP(regs);
129 return NULL;
131 REG_UNMAP(regs);
133 /* save ticks normalized to ms for si_watchdog_ms() */
134 if (PMUCTL_ENAB(&ksii.pub)) {
135 if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) {
136 /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
137 wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000;
139 else
140 /* based on 32KHz ILP clock */
141 wd_msticks = 32;
142 } else {
143 if (ksii.pub.ccrev < 18)
144 wd_msticks = si_clock(&ksii.pub) / 1000;
145 else
146 wd_msticks = si_alp_clock(&ksii.pub) / 1000;
149 ksii_attached = TRUE;
150 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
151 ksii.pub.ccrev, wd_msticks));
154 return &ksii.pub;
157 bool
158 si_ldo_war(si_t *sih, uint devid)
160 si_info_t *sii = SI_INFO(sih);
161 uint32 w;
162 chipcregs_t *cc;
163 void *regs = sii->curmap;
164 uint32 rev_id, ccst;
166 rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32));
167 rev_id &= 0xff;
168 if (!(((CHIPID(devid) == BCM4322_CHIP_ID) ||
169 (CHIPID(devid) == BCM4342_CHIP_ID) ||
170 (CHIPID(devid) == BCM4322_D11N_ID) ||
171 (CHIPID(devid) == BCM4322_D11N2G_ID) ||
172 (CHIPID(devid) == BCM4322_D11N5G_ID)) &&
173 (rev_id == 0)))
174 return TRUE;
176 SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id));
178 /* switch to chipcommon */
179 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
180 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE);
181 cc = (chipcregs_t *)regs;
183 /* clear bit 7 to fix LDO
184 * write to register *blindly* WITHOUT read since read may timeout
185 * because the default clock is 32k ILP
187 W_REG(sii->osh, &cc->regcontrol_addr, 0);
188 /* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
189 W_REG(sii->osh, &cc->regcontrol_data, 0x3001);
191 OSL_DELAY(5000);
193 /* request ALP_AVAIL through PMU to move sb out of ILP */
194 W_REG(sii->osh, &cc->min_res_mask, 0x0d);
196 SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL)
197 == 0, PMU_MAX_TRANSITION_DLY);
199 if ((ccst & CCS_ALPAVAIL) == 0) {
200 SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst));
201 return FALSE;
203 SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
205 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w);
207 return TRUE;
210 static bool
211 BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh)
213 /* need to set memseg flag for CF card first before any sb registers access */
214 if (BUSTYPE(bustype) == PCMCIA_BUS)
215 sii->memseg = TRUE;
217 if (BUSTYPE(bustype) == PCI_BUS) {
218 if (!si_ldo_war((si_t *)sii, devid))
219 return FALSE;
222 /* kludge to enable the clock on the 4306 which lacks a slowclock */
223 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
224 si_clkctl_xtal(&sii->pub, XTAL|PLL, ON);
227 return TRUE;
230 static bool
231 BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
232 uint *origidx, void *regs)
234 bool pci, pcie, pcie_gen2 = FALSE;
235 uint i;
236 uint pciidx, pcieidx, pcirev, pcierev;
238 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
239 ASSERT((uintptr)cc);
241 /* get chipcommon rev */
242 sii->pub.ccrev = (int)si_corerev(&sii->pub);
244 /* get chipcommon chipstatus */
245 if (sii->pub.ccrev >= 11)
246 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
248 /* get chipcommon capabilites */
249 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
250 /* get chipcommon extended capabilities */
252 if (sii->pub.ccrev >= 35)
253 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
255 /* get pmu rev and caps */
256 if (sii->pub.cccaps & CC_CAP_PMU) {
257 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
258 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
261 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
262 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
263 sii->pub.pmucaps));
265 /* figure out bus/orignal core idx */
266 sii->pub.buscoretype = NODEV_CORE_ID;
267 sii->pub.buscorerev = (uint)NOREV;
268 sii->pub.buscoreidx = BADIDX;
270 pci = pcie = FALSE;
271 pcirev = pcierev = (uint)NOREV;
272 pciidx = pcieidx = BADIDX;
274 for (i = 0; i < sii->numcores; i++) {
275 uint cid, crev;
277 si_setcoreidx(&sii->pub, i);
278 cid = si_coreid(&sii->pub);
279 crev = si_corerev(&sii->pub);
281 /* Display cores found */
282 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
283 i, cid, crev, sii->coresba[i], sii->regs[i]));
285 if (BUSTYPE(bustype) == PCI_BUS) {
286 if (cid == PCI_CORE_ID) {
287 pciidx = i;
288 pcirev = crev;
289 pci = TRUE;
290 } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
291 pcieidx = i;
292 pcierev = crev;
293 pcie = TRUE;
294 if (cid == PCIE2_CORE_ID)
295 pcie_gen2 = TRUE;
297 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
298 (cid == PCMCIA_CORE_ID)) {
299 sii->pub.buscorerev = crev;
300 sii->pub.buscoretype = cid;
301 sii->pub.buscoreidx = i;
304 /* find the core idx before entering this func. */
305 if ((savewin && (savewin == sii->coresba[i])) ||
306 (regs == sii->regs[i]))
307 *origidx = i;
310 if (pci && pcie) {
311 if (si_ispcie(sii))
312 pci = FALSE;
313 else
314 pcie = FALSE;
316 if (pci) {
317 sii->pub.buscoretype = PCI_CORE_ID;
318 sii->pub.buscorerev = pcirev;
319 sii->pub.buscoreidx = pciidx;
320 } else if (pcie) {
321 if (pcie_gen2)
322 sii->pub.buscoretype = PCIE2_CORE_ID;
323 else
324 sii->pub.buscoretype = PCIE_CORE_ID;
325 sii->pub.buscorerev = pcierev;
326 sii->pub.buscoreidx = pcieidx;
329 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
330 sii->pub.buscorerev));
332 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
333 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
334 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
336 /* fixup necessary chip/core configurations */
337 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
338 if (SI_FAST(sii)) {
339 if (!sii->pch &&
340 ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh,
341 (void *)PCIEREGS(sii))) == NULL))
342 return FALSE;
344 if (si_pci_fixcfg(&sii->pub)) {
345 SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
346 return FALSE;
351 /* return to the original core */
352 si_setcoreidx(&sii->pub, *origidx);
354 return TRUE;
357 static void
358 BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars)
360 uint w = 0;
361 if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
362 w = getintvar(pvars, "regwindowsz");
363 sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
366 /* get boardtype and boardrev */
367 switch (BUSTYPE(sii->pub.bustype)) {
368 case PCI_BUS:
369 /* do a pci config read to get subsystem id and subvendor id */
370 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
371 /* Let nvram variables override subsystem Vend/ID */
372 if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor"))
373 == 0) {
374 #ifdef BCMHOSTVARS
375 if ((w & 0xffff) == 0)
376 sii->pub.boardvendor = VENDOR_BROADCOM;
377 else
378 #endif /* !BCMHOSTVARS */
379 sii->pub.boardvendor = w & 0xffff;
381 else
382 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
383 sii->pub.boardvendor, w & 0xffff));
384 if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype"))
385 == 0) {
386 if ((sii->pub.boardtype = getintvar(pvars, "boardtype")) == 0)
387 sii->pub.boardtype = (w >> 16) & 0xffff;
389 else
390 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
391 sii->pub.boardtype, (w >> 16) & 0xffff));
392 break;
394 case PCMCIA_BUS:
395 sii->pub.boardvendor = getintvar(pvars, "manfid");
396 sii->pub.boardtype = getintvar(pvars, "prodid");
397 break;
400 case SI_BUS:
401 case JTAG_BUS:
402 sii->pub.boardvendor = VENDOR_BROADCOM;
403 if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
404 if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0)
405 sii->pub.boardtype = 0xffff;
407 if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
408 /* do a pci config read to get subsystem id and subvendor id */
409 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
410 sii->pub.boardvendor = w & 0xffff;
411 sii->pub.boardtype = (w >> 16) & 0xffff;
413 break;
416 if (sii->pub.boardtype == 0) {
417 SI_ERROR(("si_doattach: unknown board type\n"));
418 ASSERT(sii->pub.boardtype);
421 sii->pub.boardrev = getintvar(pvars, "boardrev");
422 sii->pub.boardflags = getintvar(pvars, "boardflags");
425 static void
426 BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars)
429 const char *sromvars[] =
430 {"extpagain2g", "extpagain5g"};
431 int sromvars_size = sizeof(sromvars)/sizeof(char *);
432 int ii;
433 uint boardtype = sih->boardtype;
434 uint boardrev = sih->boardrev;
435 bool update = ((boardtype == BCM94331BU_SSID) ||
436 (boardtype == BCM94331S9BU_SSID) ||
437 (boardtype == BCM94331MCI_SSID) ||
438 (boardtype == BCM94331MC_SSID) ||
439 (boardtype == BCM94331PCIEBT4_SSID) ||
440 (boardtype == BCM94331X19 && boardrev == 0x1100) ||
441 (boardtype == BCM94331HM_SSID && boardrev < 0x1152));
443 if (pvars == NULL || !update) {
444 return;
447 for (ii = 0; ii < sromvars_size; ii++) {
448 char* val = getvar(pvars, sromvars[ii]);
450 while (val && *val) {
451 *val = '0';
452 val++;
457 #if defined(CONFIG_XIP) && defined(BCMTCAM)
458 extern uint8 patch_pair;
459 #endif /* CONFIG_XIP && BCMTCAM */
462 typedef struct {
463 uint8 uart_tx;
464 uint32 uart_rx;
465 } si_mux4335_uartopt_t;
467 /* note: each index corr to MUXENAB4335_UART mask - 1 */
468 static const si_mux4335_uartopt_t BCMATTACHDATA(mux4335_uartopt)[] = {
469 {CC4335_PIN_GPIO_06, CC4335_PIN_GPIO_02},
470 {CC4335_PIN_GPIO_12, CC4335_PIN_GPIO_13},
471 {CC4335_PIN_SDIO_DATA0, CC4335_PIN_SDIO_CMD},
472 {CC4335_PIN_RF_SW_CTRL_9, CC4335_PIN_RF_SW_CTRL_8}
475 /* want to have this available all the time to switch mux for debugging */
476 void
477 BCMATTACHFN(si_muxenab)(si_t *sih, uint32 w)
479 uint32 chipcontrol, pmu_chipcontrol;
481 pmu_chipcontrol = si_pmu_chipcontrol(sih, 1, 0, 0);
482 chipcontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
483 0, 0);
485 switch (CHIPID(sih->chip)) {
486 case BCM4330_CHIP_ID:
487 /* clear the bits */
488 chipcontrol &= ~(CCTRL_4330_JTAG_DISABLE | CCTRL_4330_ERCX_SEL |
489 CCTRL_4330_GPIO_SEL | CCTRL_4330_SDIO_HOST_WAKE);
490 pmu_chipcontrol &= ~PCTL_4330_SERIAL_ENAB;
492 /* 4330 default is to have jtag enabled */
493 if (!(w & MUXENAB_JTAG))
494 chipcontrol |= CCTRL_4330_JTAG_DISABLE;
495 if (w & MUXENAB_UART)
496 pmu_chipcontrol |= PCTL_4330_SERIAL_ENAB;
497 if (w & MUXENAB_GPIO)
498 chipcontrol |= CCTRL_4330_GPIO_SEL;
499 if (w & MUXENAB_ERCX)
500 chipcontrol |= CCTRL_4330_ERCX_SEL;
501 if (w & MUXENAB_HOST_WAKE)
502 chipcontrol |= CCTRL_4330_SDIO_HOST_WAKE;
503 break;
504 case BCM4336_CHIP_ID:
505 if (w & MUXENAB_UART)
506 pmu_chipcontrol |= PCTL_4336_SERIAL_ENAB;
507 else
508 pmu_chipcontrol &= ~PCTL_4336_SERIAL_ENAB;
509 break;
510 case BCM4360_CHIP_ID:
511 case BCM43460_CHIP_ID:
512 case BCM4352_CHIP_ID:
513 if (w & MUXENAB_UART)
514 chipcontrol |= CCTL_4360_UART_SEL;
515 break;
517 case BCM4335_CHIP_ID:
518 /* drive default pins for UART. Note: 15 values possible;
519 * 0 means disabled; 1 means index to 0 in mux4335_uartopt
520 * array, etc.
522 if (w & MUXENAB4335_UART_MASK) {
523 uint32 uart_rx = 0, uart_tx = 0;
524 uint8 uartopt_ix = (w & MUXENAB4335_UART_MASK) - 1;
526 uart_rx = mux4335_uartopt[uartopt_ix].uart_rx;
527 uart_tx = mux4335_uartopt[uartopt_ix].uart_tx;
529 si_gci_set_functionsel(sih, uart_rx, CC4335_FNSEL_UART);
530 si_gci_set_functionsel(sih, uart_tx, CC4335_FNSEL_UART);
532 break;
534 default:
535 /* muxenab specified for an unsupported chip */
536 ASSERT(0);
537 break;
540 /* write both updated values to hw */
541 si_pmu_chipcontrol(sih, 1, ~0, pmu_chipcontrol);
542 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
543 ~0, chipcontrol);
546 /* write 'val' to the gci chip control register indexed by 'reg' */
547 uint32
548 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
550 /* because NFLASH and GCI clashes in 0xC00 */
551 #ifndef NFLASH_SUPPORT
552 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_indirect_addr), ~0, reg);
553 return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_chipctrl), mask, val);
554 #else /* NFLASH_SUPPORT */
555 ASSERT(0);
556 return 0xFFFFFFFF;
557 #endif
560 /* input: pin number
561 * output: chipcontrol reg and bits to shift for pin fn-sel's first regbit.
562 * eg: gpio9 will give regidx: 1 and pos 4
564 uint8
565 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos)
567 *regidx = (pin / 8);
568 *pos = (pin % 8)*4;
570 SI_MSG(("si_gci_get_chipctrlreg_idx:%d:%d:%d\n", pin, *regidx, *pos));
572 return 0;
575 /* setup a given pin for fnsel function */
576 void
577 si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel)
579 uint32 reg = 0, pos = 0;
581 SI_MSG(("si_gci_set_functionsel:%d\n", pin));
583 si_gci_get_chipctrlreg_idx(pin, &reg, &pos);
584 si_gci_chipcontrol(sih, reg, GCIMASK(pos), GCIPOSVAL(fnsel, pos));
587 static si_info_t *
588 BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs,
589 uint bustype, void *sdh, char **vars, uint *varsz)
591 struct si_pub *sih = &sii->pub;
592 uint32 w, savewin;
593 chipcregs_t *cc;
594 char *pvars = NULL;
595 uint origidx;
596 bool fixup_boardtype = FALSE;
597 ASSERT(GOODREGS(regs));
599 bzero((uchar*)sii, sizeof(si_info_t));
601 savewin = 0;
603 sih->buscoreidx = BADIDX;
605 sii->curmap = regs;
606 sii->sdh = sdh;
607 sii->osh = osh;
609 #ifdef SI_ENUM_BASE_VARIABLE
610 si_enum_base_init(sih, bustype);
611 #endif /* SI_ENUM_BASE_VARIABLE */
613 /* check to see if we are a si core mimic'ing a pci core */
614 if ((bustype == PCI_BUS) &&
615 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
616 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
617 "devid:0x%x\n", __FUNCTION__, devid));
618 bustype = SI_BUS;
621 /* find Chipcommon address */
622 if (bustype == PCI_BUS) {
623 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
624 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
625 savewin = SI_ENUM_BASE;
626 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
627 cc = (chipcregs_t *)regs;
628 } else {
629 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
632 sih->bustype = bustype;
633 if (bustype != BUSTYPE(bustype)) {
634 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
635 bustype, BUSTYPE(bustype)));
636 return NULL;
639 /* bus/core/clk setup for register access */
640 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
641 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
642 return NULL;
645 /* ChipID recognition.
646 * We assume we can read chipid at offset 0 from the regs arg.
647 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
648 * some way of recognizing them needs to be added here.
650 if (!cc) {
651 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
652 return NULL;
654 w = R_REG(osh, &cc->chipid);
655 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
656 /* Might as wll fill in chip id rev & pkg */
657 sih->chip = w & CID_ID_MASK;
658 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
659 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
661 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
662 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
663 sih->chippkg = BCM4329_182PIN_PKG_ID;
665 sih->issim = IS_SIM(sih->chippkg);
667 /* scan for cores */
668 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
669 SI_MSG(("Found chip type SB (0x%08x)\n", w));
670 sb_scan(&sii->pub, regs, devid);
671 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
672 SI_MSG(("Found chip type AI (0x%08x)\n", w));
673 /* pass chipc address instead of original core base */
674 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
675 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
676 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
677 /* pass chipc address instead of original core base */
678 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
679 } else {
680 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
681 return NULL;
683 /* no cores found, bail out */
684 if (sii->numcores == 0) {
685 SI_ERROR(("si_doattach: could not find any cores\n"));
686 return NULL;
688 /* bus/core/clk setup */
689 origidx = SI_CC_IDX;
690 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
691 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
692 goto exit;
695 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
696 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
697 CST4322_SPROM_PRESENT))) {
698 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
699 return NULL;
702 /* assume current core is CC */
703 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
704 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
705 CHIPID(sih->chip) == BCM43234_CHIP_ID ||
706 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
707 (CHIPREV(sii->pub.chiprev) <= 2))) {
709 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
710 uint clkdiv;
711 clkdiv = R_REG(osh, &cc->clkdiv);
712 /* otp_clk_div is even number, 120/14 < 9mhz */
713 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
714 W_REG(osh, &cc->clkdiv, clkdiv);
715 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
717 OSL_DELAY(10);
720 if (bustype == PCI_BUS) {
721 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
722 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
723 /* Check Ext PA Controls for 4331 12x9 Package before the fixup */
724 if (sih->chippkg == 9) {
725 uint32 val = si_chipcontrl_read(sih);
726 fixup_boardtype = ((val & CCTRL4331_EXTPA_ON_GPIO2_5) ==
727 CCTRL4331_EXTPA_ON_GPIO2_5);
729 /* set default mux pin to SROM */
730 si_chipcontrl_epa4331(sih, FALSE);
731 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100);
732 OSL_DELAY(20000); /* Srom read takes ~12mS */
735 if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
736 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
737 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
738 (CHIPREV(sih->chiprev) <= 2)) {
739 pcie_disable_TL_clk_gating(sii->pch);
740 pcie_set_L1_entry_time(sii->pch, 0x40);
743 #ifdef BCMQT
744 /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
745 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
746 * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words.
749 uint otpclkdiv = 0;
751 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
752 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
753 otpclkdiv = 2;
754 } else if ((CHIPID(sih->chip) == BCM43131_CHIP_ID) ||
755 (CHIPID(sih->chip) == BCM43217_CHIP_ID) ||
756 (CHIPID(sih->chip) == BCM43227_CHIP_ID) ||
757 (CHIPID(sih->chip) == BCM43228_CHIP_ID)) {
758 otpclkdiv = 4;
761 if (otpclkdiv != 0) {
762 uint clkdiv, savecore;
763 savecore = si_coreidx(sih);
764 si_setcore(sih, CC_CORE_ID, 0);
766 clkdiv = R_REG(osh, &cc->clkdiv);
767 clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT);
768 W_REG(osh, &cc->clkdiv, clkdiv);
770 SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv));
771 si_setcoreidx(sih, savecore);
774 #endif /* BCMQT */
776 #ifdef SI_SPROM_PROBE
777 si_sprom_init(sih);
778 #endif /* SI_SPROM_PROBE */
780 #if !defined(BCMHIGHSDIO)
781 /* Init nvram from flash if it exists */
782 nvram_init((void *)&(sii->pub));
784 /* Init nvram from sprom/otp if they exist */
785 if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
786 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
787 goto exit;
789 pvars = vars ? *vars : NULL;
791 si_nvram_process(sii, pvars);
793 if (bustype == PCI_BUS) {
794 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
795 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
796 si_sromvars_fixup_4331(sih, pvars);
797 if (fixup_boardtype)
798 sii->pub.boardtype = getintvar(pvars, "boardtype");
802 /* === NVRAM, clock is ready === */
803 #else
804 pvars = NULL;
805 BCM_REFERENCE(pvars);
806 #endif
809 #if defined(CONFIG_XIP) && defined(BCMTCAM)
810 /* patch the ROM if there are any patch pairs from OTP/SPROM */
811 if (patch_pair) {
813 #if defined(__ARM_ARCH_7R__)
814 hnd_tcam_bootloader_load(si_setcore(sih, ARMCR4_CORE_ID, 0), pvars);
815 #else
816 hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars);
817 #endif
818 si_setcoreidx(sih, origidx);
820 #endif /* CONFIG_XIP && BCMTCAM */
822 /* bootloader should retain default pulls */
823 #ifndef BCM_BOOTLOADER
824 if (sii->pub.ccrev >= 20) {
825 uint32 gpiopullup = 0, gpiopulldown = 0;
826 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
827 ASSERT(cc != NULL);
829 /* 4314/43142 has pin muxing, don't clear gpio bits */
830 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
831 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
832 gpiopullup |= 0x402e0;
833 gpiopulldown |= 0x20500;
836 W_REG(osh, &cc->gpiopullup, gpiopullup);
837 W_REG(osh, &cc->gpiopulldown, gpiopulldown);
838 si_setcoreidx(sih, origidx);
840 #endif /* !BCM_BOOTLOADER */
842 /* PMU specific initializations */
843 if (PMUCTL_ENAB(sih)) {
844 uint32 xtalfreq;
845 si_pmu_init(sih, sii->osh);
846 si_pmu_chip_init(sih, sii->osh);
847 xtalfreq = getintvar(pvars, "xtalfreq");
848 /* If xtalfreq var not available, try to measure it */
849 if (xtalfreq == 0)
850 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
851 #if !defined(BCMHIGHSDIO)
852 si_pmu_pll_init(sih, sii->osh, xtalfreq);
853 si_pmu_res_init(sih, sii->osh);
854 #endif
855 si_pmu_swreg_init(sih, sii->osh);
858 /* setup the GPIO based LED powersave register */
859 if (sii->pub.ccrev >= 16) {
860 if ((w = getintvar(pvars, "leddc")) == 0)
861 w = DEFAULT_GPIOTIMERVAL;
862 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
865 if (PCI_FORCEHT(sii)) {
866 SI_MSG(("si_doattach: force HT\n"));
867 sih->pci_pr32414 = TRUE;
868 si_clkctl_init(sih);
869 _si_clkctl_cc(sii, CLK_FAST);
872 if (PCIE(sii)) {
873 ASSERT(sii->pch != NULL);
875 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
877 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
878 (CHIPID(sih->chip) == BCM4312_CHIP_ID)) {
879 SI_MSG(("si_doattach: clear initiator timeout\n"));
880 sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0));
884 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
885 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
886 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
887 if (CHIPREV(sih->chiprev) == 0) {
888 SI_MSG(("Applying 43224A0 WARs\n"));
889 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
890 CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE);
891 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
892 CCTRL_43224A0_12MA_LED_DRIVE);
894 if (CHIPREV(sih->chiprev) >= 1) {
895 SI_MSG(("Applying 43224B0+ WARs\n"));
896 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
897 CCTRL_43224B0_12MA_LED_DRIVE);
901 /* configure default pinmux enables for the chip */
902 if (getvar(pvars, "muxenab") != NULL) {
903 w = getintvar(pvars, "muxenab");
904 si_muxenab((si_t *)sii, w);
907 /* enable GPIO interrupts when clocks are off */
908 if (sii->pub.ccrev >= 21) {
909 uint32 corecontrol;
910 corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
911 0, 0);
912 corecontrol |= CC_ASYNCGPIO;
913 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
914 corecontrol, corecontrol);
917 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
918 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
919 SI_MSG(("Applying 4313 WARs\n"));
920 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, CCTRL_4313_12MA_LED_DRIVE);
923 #if defined(SAVERESTORE)
924 sr_save_restore_init(sih);
925 #endif
926 /* clear any previous epidiag-induced target abort */
927 ASSERT(!si_taclear(sih, FALSE));
929 return (sii);
931 exit:
932 if (BUSTYPE(sih->bustype) == PCI_BUS) {
933 if (sii->pch)
934 pcicore_deinit(sii->pch);
935 sii->pch = NULL;
938 return NULL;
941 /* may be called with core in reset */
942 void
943 BCMATTACHFN(si_detach)(si_t *sih)
945 si_info_t *sii;
946 uint idx;
948 #if defined(STA)
949 struct si_pub *si_local = NULL;
950 bcopy(&sih, &si_local, sizeof(si_t*));
951 #endif
953 sii = SI_INFO(sih);
955 if (sii == NULL)
956 return;
958 if (BUSTYPE(sih->bustype) == SI_BUS)
959 for (idx = 0; idx < SI_MAXCORES; idx++)
960 if (sii->regs[idx]) {
961 REG_UNMAP(sii->regs[idx]);
962 sii->regs[idx] = NULL;
965 #if defined(STA)
966 #if !defined(BCMHIGHSDIO)
967 srom_var_deinit((void *)si_local);
968 #endif
969 nvram_exit((void *)si_local); /* free up nvram buffers */
970 #endif
972 if (BUSTYPE(sih->bustype) == PCI_BUS) {
973 if (sii->pch)
974 pcicore_deinit(sii->pch);
975 sii->pch = NULL;
978 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
979 if (sii != &ksii)
980 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
981 MFREE(sii->osh, sii, sizeof(si_info_t));
984 void *
985 si_osh(si_t *sih)
987 si_info_t *sii;
989 sii = SI_INFO(sih);
990 return sii->osh;
993 void
994 si_setosh(si_t *sih, osl_t *osh)
996 si_info_t *sii;
998 sii = SI_INFO(sih);
999 if (sii->osh != NULL) {
1000 SI_ERROR(("osh is already set....\n"));
1001 ASSERT(!sii->osh);
1003 sii->osh = osh;
1006 /* register driver interrupt disabling and restoring callback functions */
1007 void
1008 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
1009 void *intrsenabled_fn, void *intr_arg)
1011 si_info_t *sii;
1013 sii = SI_INFO(sih);
1014 sii->intr_arg = intr_arg;
1015 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
1016 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
1017 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
1018 /* save current core id. when this function called, the current core
1019 * must be the core which provides driver functions(il, et, wl, etc.)
1021 sii->dev_coreid = sii->coreid[sii->curidx];
1024 void
1025 si_deregister_intr_callback(si_t *sih)
1027 si_info_t *sii;
1029 sii = SI_INFO(sih);
1030 sii->intrsoff_fn = NULL;
1033 uint
1034 si_intflag(si_t *sih)
1036 si_info_t *sii = SI_INFO(sih);
1038 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1039 return sb_intflag(sih);
1040 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1041 return R_REG(sii->osh, ((uint32 *)(uintptr)
1042 (sii->oob_router + OOB_STATUSA)));
1043 else {
1044 ASSERT(0);
1045 return 0;
1049 uint
1050 si_flag(si_t *sih)
1052 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1053 return sb_flag(sih);
1054 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1055 return ai_flag(sih);
1056 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1057 return ub_flag(sih);
1058 else {
1059 ASSERT(0);
1060 return 0;
1064 void
1065 si_setint(si_t *sih, int siflag)
1067 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1068 sb_setint(sih, siflag);
1069 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1070 ai_setint(sih, siflag);
1071 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1072 ub_setint(sih, siflag);
1073 else
1074 ASSERT(0);
1077 uint
1078 si_coreid(si_t *sih)
1080 si_info_t *sii;
1082 sii = SI_INFO(sih);
1083 return sii->coreid[sii->curidx];
1086 uint
1087 si_coreidx(si_t *sih)
1089 si_info_t *sii;
1091 sii = SI_INFO(sih);
1092 return sii->curidx;
1095 /* return the core-type instantiation # of the current core */
1096 uint
1097 si_coreunit(si_t *sih)
1099 si_info_t *sii;
1100 uint idx;
1101 uint coreid;
1102 uint coreunit;
1103 uint i;
1105 sii = SI_INFO(sih);
1106 coreunit = 0;
1108 idx = sii->curidx;
1110 ASSERT(GOODREGS(sii->curmap));
1111 coreid = si_coreid(sih);
1113 /* count the cores of our type */
1114 for (i = 0; i < idx; i++)
1115 if (sii->coreid[i] == coreid)
1116 coreunit++;
1118 return (coreunit);
1121 uint
1122 si_corevendor(si_t *sih)
1124 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1125 return sb_corevendor(sih);
1126 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1127 return ai_corevendor(sih);
1128 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1129 return ub_corevendor(sih);
1130 else {
1131 ASSERT(0);
1132 return 0;
1136 bool
1137 si_backplane64(si_t *sih)
1139 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
1142 uint
1143 si_corerev(si_t *sih)
1145 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1146 return sb_corerev(sih);
1147 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1148 return ai_corerev(sih);
1149 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1150 return ub_corerev(sih);
1151 else {
1152 ASSERT(0);
1153 return 0;
1157 /* return index of coreid or BADIDX if not found */
1158 uint
1159 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
1161 si_info_t *sii;
1162 uint found;
1163 uint i;
1165 sii = SI_INFO(sih);
1167 found = 0;
1169 for (i = 0; i < sii->numcores; i++)
1170 if (sii->coreid[i] == coreid) {
1171 if (found == coreunit)
1172 return (i);
1173 found++;
1176 return (BADIDX);
1179 /* return list of found cores */
1180 uint
1181 si_corelist(si_t *sih, uint coreid[])
1183 si_info_t *sii;
1185 sii = SI_INFO(sih);
1187 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
1188 return (sii->numcores);
1191 /* return current register mapping */
1192 void *
1193 si_coreregs(si_t *sih)
1195 si_info_t *sii;
1197 sii = SI_INFO(sih);
1198 ASSERT(GOODREGS(sii->curmap));
1200 return (sii->curmap);
1204 * This function changes logical "focus" to the indicated core;
1205 * must be called with interrupts off.
1206 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1208 void *
1209 si_setcore(si_t *sih, uint coreid, uint coreunit)
1211 uint idx;
1213 idx = si_findcoreidx(sih, coreid, coreunit);
1214 if (!GOODIDX(idx))
1215 return (NULL);
1217 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1218 return sb_setcoreidx(sih, idx);
1219 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1220 return ai_setcoreidx(sih, idx);
1221 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1222 return ub_setcoreidx(sih, idx);
1223 else {
1224 ASSERT(0);
1225 return NULL;
1229 void *
1230 si_setcoreidx(si_t *sih, uint coreidx)
1232 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1233 return sb_setcoreidx(sih, coreidx);
1234 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1235 return ai_setcoreidx(sih, coreidx);
1236 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1237 return ub_setcoreidx(sih, coreidx);
1238 else {
1239 ASSERT(0);
1240 return NULL;
1244 /* Turn off interrupt as required by sb_setcore, before switch core */
1245 void *
1246 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1248 void *cc;
1249 si_info_t *sii;
1251 sii = SI_INFO(sih);
1253 if (SI_FAST(sii)) {
1254 /* Overloading the origidx variable to remember the coreid,
1255 * this works because the core ids cannot be confused with
1256 * core indices.
1258 *origidx = coreid;
1259 if (coreid == CC_CORE_ID)
1260 return (void *)CCREGS_FAST(sii);
1261 else if (coreid == sih->buscoretype)
1262 return (void *)PCIEREGS(sii);
1264 INTR_OFF(sii, *intr_val);
1265 *origidx = sii->curidx;
1266 cc = si_setcore(sih, coreid, 0);
1267 ASSERT(cc != NULL);
1269 return cc;
1272 /* restore coreidx and restore interrupt */
1273 void
1274 si_restore_core(si_t *sih, uint coreid, uint intr_val)
1276 si_info_t *sii;
1278 sii = SI_INFO(sih);
1279 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1280 return;
1282 si_setcoreidx(sih, coreid);
1283 INTR_RESTORE(sii, intr_val);
1287 si_numaddrspaces(si_t *sih)
1289 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1290 return sb_numaddrspaces(sih);
1291 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1292 return ai_numaddrspaces(sih);
1293 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1294 return ub_numaddrspaces(sih);
1295 else {
1296 ASSERT(0);
1297 return 0;
1301 uint32
1302 si_addrspace(si_t *sih, uint asidx)
1304 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1305 return sb_addrspace(sih, asidx);
1306 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1307 return ai_addrspace(sih, asidx);
1308 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1309 return ub_addrspace(sih, asidx);
1310 else {
1311 ASSERT(0);
1312 return 0;
1316 uint32
1317 si_addrspacesize(si_t *sih, uint asidx)
1319 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1320 return sb_addrspacesize(sih, asidx);
1321 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1322 return ai_addrspacesize(sih, asidx);
1323 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1324 return ub_addrspacesize(sih, asidx);
1325 else {
1326 ASSERT(0);
1327 return 0;
1331 void
1332 si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
1334 /* Only supported for SOCI_AI */
1335 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1336 ai_coreaddrspaceX(sih, asidx, addr, size);
1337 else
1338 *size = 0;
1341 uint32
1342 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1344 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1345 return sb_core_cflags(sih, mask, val);
1346 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1347 return ai_core_cflags(sih, mask, val);
1348 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1349 return ub_core_cflags(sih, mask, val);
1350 else {
1351 ASSERT(0);
1352 return 0;
1356 void
1357 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1359 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1360 sb_core_cflags_wo(sih, mask, val);
1361 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1362 ai_core_cflags_wo(sih, mask, val);
1363 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1364 ub_core_cflags_wo(sih, mask, val);
1365 else
1366 ASSERT(0);
1369 uint32
1370 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1372 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1373 return sb_core_sflags(sih, mask, val);
1374 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1375 return ai_core_sflags(sih, mask, val);
1376 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1377 return ub_core_sflags(sih, mask, val);
1378 else {
1379 ASSERT(0);
1380 return 0;
1384 bool
1385 si_iscoreup(si_t *sih)
1387 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1388 return sb_iscoreup(sih);
1389 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1390 return ai_iscoreup(sih);
1391 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1392 return ub_iscoreup(sih);
1393 else {
1394 ASSERT(0);
1395 return FALSE;
1399 uint
1400 si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
1402 /* only for AI back plane chips */
1403 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1404 return (ai_wrap_reg(sih, offset, mask, val));
1405 return 0;
1408 uint
1409 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1411 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1412 return sb_corereg(sih, coreidx, regoff, mask, val);
1413 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1414 return ai_corereg(sih, coreidx, regoff, mask, val);
1415 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1416 return ub_corereg(sih, coreidx, regoff, mask, val);
1417 else {
1418 ASSERT(0);
1419 return 0;
1423 void
1424 si_core_disable(si_t *sih, uint32 bits)
1426 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1427 sb_core_disable(sih, bits);
1428 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1429 ai_core_disable(sih, bits);
1430 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1431 ub_core_disable(sih, bits);
1434 void
1435 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1437 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1438 sb_core_reset(sih, bits, resetbits);
1439 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1440 ai_core_reset(sih, bits, resetbits);
1441 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1442 ub_core_reset(sih, bits, resetbits);
1445 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1447 si_corebist(si_t *sih)
1449 uint32 cflags;
1450 int result = 0;
1452 /* Read core control flags */
1453 cflags = si_core_cflags(sih, 0, 0);
1455 /* Set bist & fgc */
1456 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1458 /* Wait for bist done */
1459 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1461 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1462 result = BCME_ERROR;
1464 /* Reset core control flags */
1465 si_core_cflags(sih, 0xffff, cflags);
1467 return result;
1470 static uint32
1471 BCMINITFN(factor6)(uint32 x)
1473 switch (x) {
1474 case CC_F6_2: return 2;
1475 case CC_F6_3: return 3;
1476 case CC_F6_4: return 4;
1477 case CC_F6_5: return 5;
1478 case CC_F6_6: return 6;
1479 case CC_F6_7: return 7;
1480 default: return 0;
1484 /* calculate the speed the SI would run at given a set of clockcontrol values */
1485 uint32
1486 BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m)
1488 uint32 n1, n2, clock, m1, m2, m3, mc;
1490 n1 = n & CN_N1_MASK;
1491 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1493 if (pll_type == PLL_TYPE6) {
1494 if (m & CC_T6_MMASK)
1495 return CC_T6_M1;
1496 else
1497 return CC_T6_M0;
1498 } else if ((pll_type == PLL_TYPE1) ||
1499 (pll_type == PLL_TYPE3) ||
1500 (pll_type == PLL_TYPE4) ||
1501 (pll_type == PLL_TYPE7)) {
1502 n1 = factor6(n1);
1503 n2 += CC_F5_BIAS;
1504 } else if (pll_type == PLL_TYPE2) {
1505 n1 += CC_T2_BIAS;
1506 n2 += CC_T2_BIAS;
1507 ASSERT((n1 >= 2) && (n1 <= 7));
1508 ASSERT((n2 >= 5) && (n2 <= 23));
1509 } else if (pll_type == PLL_TYPE5) {
1510 return (100000000);
1511 } else
1512 ASSERT(0);
1513 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1514 if ((pll_type == PLL_TYPE3) ||
1515 (pll_type == PLL_TYPE7)) {
1516 clock = CC_CLOCK_BASE2 * n1 * n2;
1517 } else
1518 clock = CC_CLOCK_BASE1 * n1 * n2;
1520 if (clock == 0)
1521 return 0;
1523 m1 = m & CC_M1_MASK;
1524 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1525 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1526 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1528 if ((pll_type == PLL_TYPE1) ||
1529 (pll_type == PLL_TYPE3) ||
1530 (pll_type == PLL_TYPE4) ||
1531 (pll_type == PLL_TYPE7)) {
1532 m1 = factor6(m1);
1533 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1534 m2 += CC_F5_BIAS;
1535 else
1536 m2 = factor6(m2);
1537 m3 = factor6(m3);
1539 switch (mc) {
1540 case CC_MC_BYPASS: return (clock);
1541 case CC_MC_M1: return (clock / m1);
1542 case CC_MC_M1M2: return (clock / (m1 * m2));
1543 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
1544 case CC_MC_M1M3: return (clock / (m1 * m3));
1545 default: return (0);
1547 } else {
1548 ASSERT(pll_type == PLL_TYPE2);
1550 m1 += CC_T2_BIAS;
1551 m2 += CC_T2M2_BIAS;
1552 m3 += CC_T2_BIAS;
1553 ASSERT((m1 >= 2) && (m1 <= 7));
1554 ASSERT((m2 >= 3) && (m2 <= 10));
1555 ASSERT((m3 >= 2) && (m3 <= 7));
1557 if ((mc & CC_T2MC_M1BYP) == 0)
1558 clock /= m1;
1559 if ((mc & CC_T2MC_M2BYP) == 0)
1560 clock /= m2;
1561 if ((mc & CC_T2MC_M3BYP) == 0)
1562 clock /= m3;
1564 return (clock);
1568 bool si_read_pmu_autopll(si_t *sih)
1570 si_info_t *sii;
1571 sii = SI_INFO(sih);
1572 return (si_pmu_is_autoresetphyclk_disabled(sih, sii->osh));
1575 uint32
1576 BCMINITFN(si_clock)(si_t *sih)
1578 si_info_t *sii;
1579 chipcregs_t *cc;
1580 uint32 n, m;
1581 uint idx;
1582 uint32 pll_type, rate;
1583 uint intr_val = 0;
1585 sii = SI_INFO(sih);
1586 INTR_OFF(sii, intr_val);
1587 if (PMUCTL_ENAB(sih)) {
1588 rate = si_pmu_si_clock(sih, sii->osh);
1589 goto exit;
1592 idx = sii->curidx;
1593 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1594 ASSERT(cc != NULL);
1596 n = R_REG(sii->osh, &cc->clockcontrol_n);
1597 pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1598 if (pll_type == PLL_TYPE6)
1599 m = R_REG(sii->osh, &cc->clockcontrol_m3);
1600 else if (pll_type == PLL_TYPE3)
1601 m = R_REG(sii->osh, &cc->clockcontrol_m2);
1602 else
1603 m = R_REG(sii->osh, &cc->clockcontrol_sb);
1605 /* calculate rate */
1606 rate = si_clock_rate(pll_type, n, m);
1608 if (pll_type == PLL_TYPE3)
1609 rate = rate / 2;
1611 /* switch back to previous core */
1612 si_setcoreidx(sih, idx);
1613 exit:
1614 INTR_RESTORE(sii, intr_val);
1616 return rate;
1619 uint32
1620 BCMINITFN(si_alp_clock)(si_t *sih)
1622 if (PMUCTL_ENAB(sih))
1623 return si_pmu_alp_clock(sih, si_osh(sih));
1625 return ALP_CLOCK;
1628 uint32
1629 BCMINITFN(si_ilp_clock)(si_t *sih)
1631 if (PMUCTL_ENAB(sih))
1632 return si_pmu_ilp_clock(sih, si_osh(sih));
1634 return ILP_CLOCK;
1637 /* set chip watchdog reset timer to fire in 'ticks' */
1638 void
1639 si_watchdog(si_t *sih, uint ticks)
1641 uint nb, maxt;
1643 if (PMUCTL_ENAB(sih)) {
1645 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1646 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1647 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1648 si_setcore(sih, USB20D_CORE_ID, 0);
1649 si_core_disable(sih, 1);
1650 si_setcore(sih, CC_CORE_ID, 0);
1653 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
1654 nb = 32;
1655 else
1656 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1657 /* The mips compiler uses the sllv instruction,
1658 * so we specially handle the 32-bit case.
1660 if (nb == 32)
1661 maxt = 0xffffffff;
1662 else
1663 maxt = ((1 << nb) - 1);
1665 if (ticks == 1)
1666 ticks = 2;
1667 else if (ticks > maxt)
1668 ticks = maxt;
1670 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1671 } else {
1672 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1673 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1674 maxt = (1 << 28) - 1;
1675 if (ticks > maxt)
1676 ticks = maxt;
1678 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1682 /* trigger watchdog reset after ms milliseconds */
1683 void
1684 si_watchdog_ms(si_t *sih, uint32 ms)
1686 si_watchdog(sih, wd_msticks * ms);
1689 uint32
1690 si_watchdog_msticks(void)
1692 return wd_msticks;
1695 #if defined(BCMDBG_ERR) || defined(BCMASSERT_SUPPORT)
1696 bool
1697 si_taclear(si_t *sih, bool details)
1699 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1700 return sb_taclear(sih, details);
1701 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1702 return FALSE;
1703 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1704 return FALSE;
1705 else {
1706 ASSERT(0);
1707 return FALSE;
1710 #endif
1712 uint16
1713 BCMATTACHFN(si_d11_devid)(si_t *sih)
1715 si_info_t *sii = SI_INFO(sih);
1716 uint16 device;
1718 /* Fix device id for dual band BCM4328 */
1719 if (CHIPID(sih->chip) == BCM4328_CHIP_ID &&
1720 (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID))
1721 device = BCM4328_D11DUAL_ID;
1722 else {
1723 /* normal case: nvram variable with devpath->devid->wl0id */
1724 if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0)
1726 /* Get devid from OTP/SPROM depending on where the SROM is read */
1727 else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0)
1729 /* no longer support wl0id, but keep the code here for backward compatibility. */
1730 else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0)
1732 else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) {
1733 /* Chip specific conversion */
1734 if (sih->chippkg == BCM4712SMALL_PKG_ID)
1735 device = BCM4306_D11G_ID;
1736 else
1737 device = BCM4306_D11DUAL_ID;
1738 } else {
1739 /* ignore it */
1740 device = 0xffff;
1743 return device;
1747 BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
1748 uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
1749 uint8 *pciheader)
1751 uint16 vendor = 0xffff, device = 0xffff;
1752 uint8 class, subclass, progif = 0;
1753 uint8 header = PCI_HEADER_NORMAL;
1754 uint32 core = si_coreid(sih);
1756 /* Verify whether the function exists for the core */
1757 if (func >= (uint)(core == USB20H_CORE_ID ? 2 : 1))
1758 return BCME_ERROR;
1760 /* Known vendor translations */
1761 switch (si_corevendor(sih)) {
1762 case SB_VEND_BCM:
1763 case MFGID_BRCM:
1764 vendor = VENDOR_BROADCOM;
1765 break;
1766 default:
1767 return BCME_ERROR;
1770 /* Determine class based on known core codes */
1771 switch (core) {
1772 case ENET_CORE_ID:
1773 class = PCI_CLASS_NET;
1774 subclass = PCI_NET_ETHER;
1775 device = BCM47XX_ENET_ID;
1776 break;
1777 case GIGETH_CORE_ID:
1778 class = PCI_CLASS_NET;
1779 subclass = PCI_NET_ETHER;
1780 device = BCM47XX_GIGETH_ID;
1781 break;
1782 case GMAC_CORE_ID:
1783 class = PCI_CLASS_NET;
1784 subclass = PCI_NET_ETHER;
1785 device = BCM47XX_GMAC_ID;
1786 break;
1787 case SDRAM_CORE_ID:
1788 case MEMC_CORE_ID:
1789 case DMEMC_CORE_ID:
1790 case SOCRAM_CORE_ID:
1791 class = PCI_CLASS_MEMORY;
1792 subclass = PCI_MEMORY_RAM;
1793 device = (uint16)core;
1794 break;
1795 case PCI_CORE_ID:
1796 case PCIE_CORE_ID:
1797 case PCIE2_CORE_ID:
1798 class = PCI_CLASS_BRIDGE;
1799 subclass = PCI_BRIDGE_PCI;
1800 device = (uint16)core;
1801 header = PCI_HEADER_BRIDGE;
1802 break;
1803 case MIPS33_CORE_ID:
1804 case MIPS74K_CORE_ID:
1805 class = PCI_CLASS_CPU;
1806 subclass = PCI_CPU_MIPS;
1807 device = (uint16)core;
1808 break;
1809 case CODEC_CORE_ID:
1810 class = PCI_CLASS_COMM;
1811 subclass = PCI_COMM_MODEM;
1812 device = BCM47XX_V90_ID;
1813 break;
1814 case I2S_CORE_ID:
1815 class = PCI_CLASS_MMEDIA;
1816 subclass = PCI_MMEDIA_AUDIO;
1817 device = BCM47XX_AUDIO_ID;
1818 break;
1819 case USB_CORE_ID:
1820 case USB11H_CORE_ID:
1821 class = PCI_CLASS_SERIAL;
1822 subclass = PCI_SERIAL_USB;
1823 progif = 0x10; /* OHCI */
1824 device = BCM47XX_USBH_ID;
1825 break;
1826 case USB20H_CORE_ID:
1827 class = PCI_CLASS_SERIAL;
1828 subclass = PCI_SERIAL_USB;
1829 progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
1830 device = BCM47XX_USB20H_ID;
1831 header = 0x80; /* multifunction */
1832 break;
1833 case IPSEC_CORE_ID:
1834 class = PCI_CLASS_CRYPT;
1835 subclass = PCI_CRYPT_NETWORK;
1836 device = BCM47XX_IPSEC_ID;
1837 break;
1838 case ROBO_CORE_ID:
1839 /* Don't use class NETWORK, so wl/et won't attempt to recognize it */
1840 class = PCI_CLASS_COMM;
1841 subclass = PCI_COMM_OTHER;
1842 device = BCM47XX_ROBO_ID;
1843 break;
1844 case CC_CORE_ID:
1845 class = PCI_CLASS_MEMORY;
1846 subclass = PCI_MEMORY_FLASH;
1847 device = (uint16)core;
1848 break;
1849 case SATAXOR_CORE_ID:
1850 class = PCI_CLASS_XOR;
1851 subclass = PCI_XOR_QDMA;
1852 device = BCM47XX_SATAXOR_ID;
1853 break;
1854 case ATA100_CORE_ID:
1855 class = PCI_CLASS_DASDI;
1856 subclass = PCI_DASDI_IDE;
1857 device = BCM47XX_ATA100_ID;
1858 break;
1859 case USB11D_CORE_ID:
1860 class = PCI_CLASS_SERIAL;
1861 subclass = PCI_SERIAL_USB;
1862 device = BCM47XX_USBD_ID;
1863 break;
1864 case USB20D_CORE_ID:
1865 class = PCI_CLASS_SERIAL;
1866 subclass = PCI_SERIAL_USB;
1867 device = BCM47XX_USB20D_ID;
1868 break;
1869 case D11_CORE_ID:
1870 class = PCI_CLASS_NET;
1871 subclass = PCI_NET_OTHER;
1872 device = si_d11_devid(sih);
1873 break;
1875 default:
1876 class = subclass = progif = 0xff;
1877 device = (uint16)core;
1878 break;
1881 *pcivendor = vendor;
1882 *pcidevice = device;
1883 *pciclass = class;
1884 *pcisubclass = subclass;
1885 *pciprogif = progif;
1886 *pciheader = header;
1888 return 0;
1891 #if defined(BCMDBG)
1892 /* print interesting sbconfig registers */
1893 void
1894 si_dumpregs(si_t *sih, struct bcmstrbuf *b)
1896 si_info_t *sii;
1897 uint origidx, intr_val = 0;
1899 sii = SI_INFO(sih);
1900 origidx = sii->curidx;
1902 INTR_OFF(sii, intr_val);
1903 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1904 sb_dumpregs(sih, b);
1905 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1906 ai_dumpregs(sih, b);
1907 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1908 ub_dumpregs(sih, b);
1909 else
1910 ASSERT(0);
1912 si_setcoreidx(sih, origidx);
1913 INTR_RESTORE(sii, intr_val);
1915 #endif
1917 #ifdef BCMDBG
1918 void
1919 si_view(si_t *sih, bool verbose)
1921 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1922 sb_view(sih, verbose);
1923 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1924 ai_view(sih, verbose);
1925 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1926 ub_view(sih, verbose);
1927 else
1928 ASSERT(0);
1931 void
1932 si_viewall(si_t *sih, bool verbose)
1934 si_info_t *sii;
1935 uint curidx, i;
1936 uint intr_val = 0;
1938 sii = SI_INFO(sih);
1939 curidx = sii->curidx;
1941 INTR_OFF(sii, intr_val);
1942 if (CHIPTYPE(sih->socitype) == SOCI_AI)
1943 ai_viewall(sih, verbose);
1944 else {
1945 SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores));
1946 for (i = 0; i < sii->numcores; i++) {
1947 si_setcoreidx(sih, i);
1948 si_view(sih, verbose);
1951 si_setcoreidx(sih, curidx);
1952 INTR_RESTORE(sii, intr_val);
1954 #endif /* BCMDBG */
1956 /* return the slow clock source - LPO, XTAL, or PCI */
1957 static uint
1958 si_slowclk_src(si_info_t *sii)
1960 chipcregs_t *cc;
1962 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1964 if (sii->pub.ccrev < 6) {
1965 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1966 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1967 PCI_CFG_GPIO_SCS))
1968 return (SCC_SS_PCI);
1969 else
1970 return (SCC_SS_XTAL);
1971 } else if (sii->pub.ccrev < 10) {
1972 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1973 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1974 } else /* Insta-clock */
1975 return (SCC_SS_XTAL);
1978 /* return the ILP (slowclock) min or max frequency */
1979 static uint
1980 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1982 uint32 slowclk;
1983 uint div;
1985 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1987 /* shouldn't be here unless we've established the chip has dynamic clk control */
1988 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1990 slowclk = si_slowclk_src(sii);
1991 if (sii->pub.ccrev < 6) {
1992 if (slowclk == SCC_SS_PCI)
1993 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1994 else
1995 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1996 } else if (sii->pub.ccrev < 10) {
1997 div = 4 *
1998 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1999 if (slowclk == SCC_SS_LPO)
2000 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
2001 else if (slowclk == SCC_SS_XTAL)
2002 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
2003 else if (slowclk == SCC_SS_PCI)
2004 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
2005 else
2006 ASSERT(0);
2007 } else {
2008 /* Chipc rev 10 is InstaClock */
2009 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
2010 div = 4 * (div + 1);
2011 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
2013 return (0);
2016 static void
2017 BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs)
2019 chipcregs_t *cc = (chipcregs_t *)chipcregs;
2020 uint slowmaxfreq, pll_delay, slowclk;
2021 uint pll_on_delay, fref_sel_delay;
2023 pll_delay = PLL_DELAY;
2025 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
2026 * since the xtal will also be powered down by dynamic clk control logic.
2029 slowclk = si_slowclk_src(sii);
2030 if (slowclk != SCC_SS_XTAL)
2031 pll_delay += XTAL_ON_DELAY;
2033 /* Starting with 4318 it is ILP that is used for the delays */
2034 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
2036 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
2037 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
2039 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
2040 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
2043 /* initialize power control delay registers */
2044 void
2045 BCMINITFN(si_clkctl_init)(si_t *sih)
2047 si_info_t *sii;
2048 uint origidx = 0;
2049 chipcregs_t *cc;
2050 bool fast;
2052 if (!CCCTL_ENAB(sih))
2053 return;
2055 sii = SI_INFO(sih);
2056 fast = SI_FAST(sii);
2057 if (!fast) {
2058 origidx = sii->curidx;
2059 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2060 return;
2061 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2062 return;
2063 ASSERT(cc != NULL);
2065 /* set all Instaclk chip ILP to 1 MHz */
2066 if (sih->ccrev >= 10)
2067 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
2068 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
2070 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
2072 if (!fast)
2073 si_setcoreidx(sih, origidx);
2076 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
2077 uint16
2078 BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih)
2080 si_info_t *sii;
2081 uint origidx = 0;
2082 chipcregs_t *cc;
2083 uint slowminfreq;
2084 uint16 fpdelay;
2085 uint intr_val = 0;
2086 bool fast;
2088 sii = SI_INFO(sih);
2089 if (PMUCTL_ENAB(sih)) {
2090 INTR_OFF(sii, intr_val);
2091 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
2092 INTR_RESTORE(sii, intr_val);
2093 return fpdelay;
2096 if (!CCCTL_ENAB(sih))
2097 return 0;
2099 fast = SI_FAST(sii);
2100 fpdelay = 0;
2101 if (!fast) {
2102 origidx = sii->curidx;
2103 INTR_OFF(sii, intr_val);
2104 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2105 goto done;
2107 else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2108 goto done;
2109 ASSERT(cc != NULL);
2111 slowminfreq = si_slowclk_freq(sii, FALSE, cc);
2112 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
2113 (slowminfreq - 1)) / slowminfreq;
2115 done:
2116 if (!fast) {
2117 si_setcoreidx(sih, origidx);
2118 INTR_RESTORE(sii, intr_val);
2120 return fpdelay;
2123 /* turn primary xtal and/or pll off/on */
2125 si_clkctl_xtal(si_t *sih, uint what, bool on)
2127 si_info_t *sii;
2128 uint32 in, out, outen;
2130 sii = SI_INFO(sih);
2132 switch (BUSTYPE(sih->bustype)) {
2135 case PCMCIA_BUS:
2136 return (0);
2139 case PCI_BUS:
2140 /* pcie core doesn't have any mapping to control the xtal pu */
2141 if (PCIE(sii))
2142 return -1;
2144 in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
2145 out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
2146 outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32));
2149 * Avoid glitching the clock if GPRS is already using it.
2150 * We can't actually read the state of the PLLPD so we infer it
2151 * by the value of XTAL_PU which *is* readable via gpioin.
2153 if (on && (in & PCI_CFG_GPIO_XTAL))
2154 return (0);
2156 if (what & XTAL)
2157 outen |= PCI_CFG_GPIO_XTAL;
2158 if (what & PLL)
2159 outen |= PCI_CFG_GPIO_PLL;
2161 if (on) {
2162 /* turn primary xtal on */
2163 if (what & XTAL) {
2164 out |= PCI_CFG_GPIO_XTAL;
2165 if (what & PLL)
2166 out |= PCI_CFG_GPIO_PLL;
2167 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2168 sizeof(uint32), out);
2169 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
2170 sizeof(uint32), outen);
2171 OSL_DELAY(XTAL_ON_DELAY);
2174 /* turn pll on */
2175 if (what & PLL) {
2176 out &= ~PCI_CFG_GPIO_PLL;
2177 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2178 sizeof(uint32), out);
2179 OSL_DELAY(2000);
2181 } else {
2182 if (what & XTAL)
2183 out &= ~PCI_CFG_GPIO_XTAL;
2184 if (what & PLL)
2185 out |= PCI_CFG_GPIO_PLL;
2186 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out);
2187 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32),
2188 outen);
2190 return 0;
2192 default:
2193 return (-1);
2196 return (0);
2200 * clock control policy function throught chipcommon
2202 * set dynamic clk control mode (forceslow, forcefast, dynamic)
2203 * returns true if we are forcing fast clock
2204 * this is a wrapper over the next internal function
2205 * to allow flexible policy settings for outside caller
2207 bool
2208 si_clkctl_cc(si_t *sih, uint mode)
2210 si_info_t *sii;
2212 sii = SI_INFO(sih);
2214 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2215 if (sih->ccrev < 6)
2216 return FALSE;
2218 if (PCI_FORCEHT(sii))
2219 return (mode == CLK_FAST);
2221 return _si_clkctl_cc(sii, mode);
2224 /* clk control mechanism through chipcommon, no policy checking */
2225 static bool
2226 _si_clkctl_cc(si_info_t *sii, uint mode)
2228 uint origidx = 0;
2229 chipcregs_t *cc;
2230 uint32 scc;
2231 uint intr_val = 0;
2232 bool fast = SI_FAST(sii);
2234 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2235 if (sii->pub.ccrev < 6)
2236 return (FALSE);
2238 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
2239 ASSERT(sii->pub.ccrev != 10);
2241 if (!fast) {
2242 INTR_OFF(sii, intr_val);
2243 origidx = sii->curidx;
2245 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
2246 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
2247 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
2248 goto done;
2250 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
2251 } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
2252 goto done;
2253 ASSERT(cc != NULL);
2255 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
2256 goto done;
2258 switch (mode) {
2259 case CLK_FAST: /* FORCEHT, fast (pll) clock */
2260 if (sii->pub.ccrev < 10) {
2261 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2262 si_clkctl_xtal(&sii->pub, XTAL, ON);
2263 SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
2264 } else if (sii->pub.ccrev < 20) {
2265 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
2266 } else {
2267 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
2270 /* wait for the PLL */
2271 if (PMUCTL_ENAB(&sii->pub)) {
2272 uint32 htavail = CCS_HTAVAIL;
2273 if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2274 htavail = CCS0_HTAVAIL;
2275 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0),
2276 PMU_MAX_TRANSITION_DLY);
2277 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
2278 } else {
2279 OSL_DELAY(PLL_DELAY);
2281 break;
2283 case CLK_DYNAMIC: /* enable dynamic clock control */
2284 if (sii->pub.ccrev < 10) {
2285 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
2286 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
2287 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
2288 scc |= SCC_XC;
2289 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
2291 /* for dynamic control, we have to release our xtal_pu "force on" */
2292 if (scc & SCC_XC)
2293 si_clkctl_xtal(&sii->pub, XTAL, OFF);
2294 } else if (sii->pub.ccrev < 20) {
2295 /* Instaclock */
2296 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
2297 } else {
2298 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
2300 break;
2302 default:
2303 ASSERT(0);
2306 done:
2307 if (!fast) {
2308 si_setcoreidx(&sii->pub, origidx);
2309 INTR_RESTORE(sii, intr_val);
2311 return (mode == CLK_FAST);
2314 /* Build device path. Support SI, PCI, and JTAG for now. */
2316 BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size)
2318 int slen;
2320 ASSERT(path != NULL);
2321 ASSERT(size >= SI_DEVPATH_BUFSZ);
2323 if (!path || size <= 0)
2324 return -1;
2326 switch (BUSTYPE(sih->bustype)) {
2327 case SI_BUS:
2328 case JTAG_BUS:
2329 slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih));
2330 break;
2331 case PCI_BUS:
2332 ASSERT((SI_INFO(sih))->osh != NULL);
2333 slen = snprintf(path, (size_t)size, "pci/%u/%u/",
2334 OSL_PCI_BUS((SI_INFO(sih))->osh),
2335 OSL_PCI_SLOT((SI_INFO(sih))->osh));
2336 break;
2337 case PCMCIA_BUS:
2338 SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
2339 SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
2340 slen = snprintf(path, (size_t)size, "pc/1/1/");
2341 break;
2342 default:
2343 slen = -1;
2344 ASSERT(0);
2345 break;
2348 if (slen < 0 || slen >= size) {
2349 path[0] = '\0';
2350 return -1;
2353 return 0;
2356 char *
2357 BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name)
2359 char pathname[SI_DEVPATH_BUFSZ + 32];
2360 char devpath[SI_DEVPATH_BUFSZ + 32];
2361 char *p;
2362 int idx;
2363 int len;
2365 /* try to get compact devpath if it exist */
2366 if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) {
2367 len = strlen(devpath);
2368 devpath[len - 1] = '\0';
2369 for (idx = 0; idx < SI_MAXCORES; idx++) {
2370 snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx);
2371 if ((p = getvar(NULL, pathname)) == NULL)
2372 continue;
2374 if (strncmp(p, devpath, len) == 0) {
2375 snprintf(varname, var_len, "%d:%s", idx, name);
2376 return varname;
2381 return NULL;
2384 /* Get a variable, but only if it has a devpath prefix */
2385 char *
2386 BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name)
2388 char varname[SI_DEVPATH_BUFSZ + 32];
2389 char *val;
2391 si_devpathvar(sih, varname, sizeof(varname), name);
2393 if ((val = getvar(NULL, varname)) != NULL)
2394 return val;
2396 /* try to get compact devpath if it exist */
2397 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2398 return NULL;
2400 return (getvar(NULL, varname));
2403 /* Get a variable, but only if it has a devpath prefix */
2405 BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name)
2407 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
2408 return (getintvar(NULL, name));
2409 #else
2410 char varname[SI_DEVPATH_BUFSZ + 32];
2411 int val;
2413 si_devpathvar(sih, varname, sizeof(varname), name);
2415 if ((val = getintvar(NULL, varname)) != 0)
2416 return val;
2418 /* try to get compact devpath if it exist */
2419 if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2420 return 0;
2422 return (getintvar(NULL, varname));
2423 #endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
2426 #ifndef DONGLEBUILD
2427 char *
2428 si_getnvramflvar(si_t *sih, const char *name)
2430 return (getvar(NULL, name));
2432 #endif /* DONGLEBUILD */
2434 /* Concatenate the dev path with a varname into the given 'var' buffer
2435 * and return the 'var' pointer.
2436 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
2437 * On overflow, the first char will be set to '\0'.
2439 static char *
2440 BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name)
2442 uint path_len;
2444 if (!var || len <= 0)
2445 return var;
2447 if (si_devpath(sih, var, len) == 0) {
2448 path_len = strlen(var);
2450 if (strlen(name) + 1 > (uint)(len - path_len))
2451 var[0] = '\0';
2452 else
2453 strncpy(var + path_len, name, len - path_len - 1);
2456 return var;
2460 uint32
2461 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
2463 si_info_t *sii;
2465 sii = SI_INFO(sih);
2467 if (!PCIE(sii)) {
2468 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2469 return 0;
2472 return pcicore_pciereg(sii->pch, offset, mask, val, type);
2475 uint32
2476 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
2478 si_info_t *sii;
2480 sii = SI_INFO(sih);
2482 if (!PCIE(sii)) {
2483 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2484 return 0;
2487 return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
2491 /* return TRUE if PCIE capability exists in the pci config space */
2492 static bool
2493 si_ispcie(si_info_t *sii)
2495 uint8 cap_ptr;
2497 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2498 return FALSE;
2500 cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL);
2501 if (!cap_ptr)
2502 return FALSE;
2504 return TRUE;
2507 /* Wake-on-wireless-LAN (WOWL) support functions */
2508 /* Enable PME generation and disable clkreq */
2509 void
2510 si_pci_pmeen(si_t *sih)
2512 si_info_t *sii;
2514 sii = SI_INFO(sih);
2516 pcicore_pmeen(sii->pch);
2519 /* Return TRUE if PME status is set */
2520 bool
2521 si_pci_pmestat(si_t *sih)
2523 si_info_t *sii;
2525 sii = SI_INFO(sih);
2527 return pcicore_pmestat(sii->pch);
2530 /* Disable PME generation, clear the PME status bit if set */
2531 void
2532 si_pci_pmeclr(si_t *sih)
2534 si_info_t *sii;
2536 sii = SI_INFO(sih);
2538 pcicore_pmeclr(sii->pch);
2541 void
2542 si_pci_pmestatclr(si_t *sih)
2544 si_info_t *sii;
2546 sii = SI_INFO(sih);
2548 pcicore_pmestatclr(sii->pch);
2551 /* initialize the pcmcia core */
2552 void
2553 si_pcmcia_init(si_t *sih)
2555 si_info_t *sii;
2556 uint8 cor = 0;
2558 sii = SI_INFO(sih);
2560 /* enable d11 mac interrupts */
2561 OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2562 cor |= COR_IRQEN | COR_FUNEN;
2563 OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2568 bool
2569 BCMATTACHFN(si_pci_war16165)(si_t *sih)
2571 si_info_t *sii;
2573 sii = SI_INFO(sih);
2575 return (PCI(sii) && (sih->buscorerev <= 10));
2578 /* Disable pcie_war_ovr for some platforms (sigh!)
2579 * This is for boards that have BFL2_PCIEWAR_OVR set
2580 * but are in systems that still want the benefits of ASPM
2581 * Note that this should be done AFTER si_doattach
2583 void
2584 si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
2586 si_info_t *sii;
2588 sii = SI_INFO(sih);
2590 if (!PCIE_GEN1(sii))
2591 return;
2593 pcie_war_ovr_aspm_update(sii->pch, aspm);
2596 void
2597 si_pcie_power_save_enable(si_t *sih, bool enable)
2599 si_info_t *sii;
2601 sii = SI_INFO(sih);
2603 if (!PCIE_GEN1(sii))
2604 return;
2606 pcie_power_save_enable(sii->pch, enable);
2609 void
2610 si_pcie_set_maxpayload_size(si_t *sih, uint16 size)
2612 si_info_t *sii;
2614 sii = SI_INFO(sih);
2616 if (!PCIE(sii))
2617 return;
2619 pcie_set_maxpayload_size(sii->pch, size);
2622 uint16
2623 si_pcie_get_maxpayload_size(si_t *sih)
2625 si_info_t *sii;
2627 sii = SI_INFO(sih);
2629 if (!PCIE(sii))
2630 return (0);
2632 return pcie_get_maxpayload_size(sii->pch);
2635 void
2636 si_pcie_set_request_size(si_t *sih, uint16 size)
2638 si_info_t *sii;
2640 sii = SI_INFO(sih);
2642 if (!PCIE(sii))
2643 return;
2645 pcie_set_request_size(sii->pch, size);
2648 uint16
2649 si_pcie_get_request_size(si_t *sih)
2651 si_info_t *sii;
2653 sii = SI_INFO(sih);
2655 if (!PCIE_GEN1(sii))
2656 return (0);
2658 return pcie_get_request_size(sii->pch);
2662 uint16
2663 si_pcie_get_ssid(si_t *sih)
2665 si_info_t *sii;
2667 sii = SI_INFO(sih);
2669 if (!PCIE_GEN1(sii))
2670 return (0);
2672 return pcie_get_ssid(sii->pch);
2675 uint32
2676 si_pcie_get_bar0(si_t *sih)
2678 si_info_t *sii;
2680 sii = SI_INFO(sih);
2682 if (!PCIE(sii))
2683 return (0);
2685 return pcie_get_bar0(sii->pch);
2689 si_pcie_configspace_cache(si_t *sih)
2691 si_info_t *sii;
2693 sii = SI_INFO(sih);
2695 if (!PCIE(sii))
2696 return -1;
2698 return pcie_configspace_cache(sii->pch);
2702 si_pcie_configspace_restore(si_t *sih)
2704 si_info_t *sii;
2706 sii = SI_INFO(sih);
2708 if (!PCIE(sii))
2709 return -1;
2711 return pcie_configspace_restore(sii->pch);
2715 si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size)
2717 si_info_t *sii;
2719 sii = SI_INFO(sih);
2721 if (!PCIE(sii) || size > PCI_CONFIG_SPACE_SIZE)
2722 return -1;
2724 return pcie_configspace_get(sii->pch, buf, size);
2727 /* back door for other module to override chippkg */
2728 void
2729 si_chippkg_set(si_t *sih, uint val)
2731 si_info_t *sii;
2733 sii = SI_INFO(sih);
2735 sii->pub.chippkg = val;
2738 void
2739 BCMINITFN(si_pci_up)(si_t *sih)
2741 si_info_t *sii;
2743 sii = SI_INFO(sih);
2745 /* if not pci bus, we're done */
2746 if (BUSTYPE(sih->bustype) != PCI_BUS)
2747 return;
2749 if (PCI_FORCEHT(sii))
2750 _si_clkctl_cc(sii, CLK_FAST);
2752 if (PCIE(sii)) {
2753 pcicore_up(sii->pch, SI_PCIUP);
2754 if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
2755 (CHIPID(sih->chip) == BCM4312_CHIP_ID))
2756 sb_set_initiator_to((void *)sii, 0x3,
2757 si_findcoreidx((void *)sii, D11_CORE_ID, 0));
2761 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2762 void
2763 BCMUNINITFN(si_pci_sleep)(si_t *sih)
2765 si_info_t *sii;
2767 do_4360_pcie2_war = 0;
2769 sii = SI_INFO(sih);
2771 pcicore_sleep(sii->pch);
2774 /* Unconfigure and/or apply various WARs when going down */
2775 void
2776 BCMINITFN(si_pci_down)(si_t *sih)
2778 si_info_t *sii;
2780 sii = SI_INFO(sih);
2782 /* if not pci bus, we're done */
2783 if (BUSTYPE(sih->bustype) != PCI_BUS)
2784 return;
2786 /* release FORCEHT since chip is going to "down" state */
2787 if (PCI_FORCEHT(sii))
2788 _si_clkctl_cc(sii, CLK_DYNAMIC);
2790 pcicore_down(sii->pch, SI_PCIDOWN);
2794 * Configure the pci core for pci client (NIC) action
2795 * coremask is the bitvec of cores by index to be enabled.
2797 void
2798 BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask)
2800 si_info_t *sii;
2801 sbpciregs_t *pciregs = NULL;
2802 uint32 siflag = 0, w;
2803 uint idx = 0;
2805 sii = SI_INFO(sih);
2807 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2808 return;
2810 ASSERT(PCI(sii) || PCIE(sii));
2811 ASSERT(sii->pub.buscoreidx != BADIDX);
2813 if (PCI(sii)) {
2814 /* get current core index */
2815 idx = sii->curidx;
2817 /* we interrupt on this backplane flag number */
2818 siflag = si_flag(sih);
2820 /* switch over to pci core */
2821 pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx);
2825 * Enable sb->pci interrupts. Assume
2826 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2828 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2829 /* pci config write to set this core bit in PCIIntMask */
2830 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2831 w |= (coremask << PCI_SBIM_SHIFT);
2832 #ifdef USER_MODE
2833 /* User mode operate with interrupt disabled */
2834 w &= !(coremask << PCI_SBIM_SHIFT);
2835 #endif
2836 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2837 } else {
2838 /* set sbintvec bit for our flag number */
2839 si_setint(sih, siflag);
2842 if (PCI(sii)) {
2843 OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST));
2844 if (sii->pub.buscorerev >= 11) {
2845 OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
2846 w = R_REG(sii->osh, &pciregs->clkrun);
2847 W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL));
2848 w = R_REG(sii->osh, &pciregs->clkrun);
2851 /* switch back to previous core */
2852 si_setcoreidx(sih, idx);
2856 uint8
2857 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2859 si_info_t *sii;
2861 sii = SI_INFO(sih);
2863 if (!PCIE(sii))
2864 return 0;
2866 return pcie_clkreq(sii->pch, mask, val);
2869 uint32
2870 si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2872 si_info_t *sii;
2874 sii = SI_INFO(sih);
2876 if (!PCIE(sii))
2877 return 0;
2879 return pcie_lcreg(sii->pch, mask, val);
2882 void
2883 si_pcie_set_error_injection(si_t *sih, uint32 mode)
2885 si_info_t *sii;
2887 sii = SI_INFO(sih);
2889 if (!PCIE(sii))
2890 return;
2892 pcie_set_error_injection(sii->pch, mode);
2895 /* indirect way to read pcie config regs */
2896 uint
2897 si_pcie_readreg(void *sih, uint addrtype, uint offset)
2899 return pcie_readreg(sih, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
2900 addrtype, offset);
2904 * Fixup SROMless PCI device's configuration.
2905 * The current core may be changed upon return.
2908 si_pci_fixcfg(si_t *sih)
2910 uint origidx, pciidx;
2911 sbpciregs_t *pciregs = NULL;
2912 sbpcieregs_t *pcieregs = NULL;
2913 uint16 val16, *reg16 = NULL;
2914 uint32 w;
2916 si_info_t *sii = SI_INFO(sih);
2918 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2920 if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) {
2921 w = (CHIPREV(sii->pub.chiprev) == 0) ?
2922 CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT;
2923 si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w);
2926 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2927 /* save the current index */
2928 origidx = si_coreidx(&sii->pub);
2930 /* check 'pi' is correct and fix it if not */
2931 if (sii->pub.buscoretype == PCIE2_CORE_ID) {
2932 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE2_CORE_ID, 0);
2933 ASSERT(pcieregs != NULL);
2934 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2935 } else if (sii->pub.buscoretype == PCIE_CORE_ID) {
2936 pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2937 ASSERT(pcieregs != NULL);
2938 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2939 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
2940 pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
2941 ASSERT(pciregs != NULL);
2942 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2944 pciidx = si_coreidx(&sii->pub);
2946 if (!reg16) return -1;
2948 val16 = R_REG(sii->osh, reg16);
2949 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
2950 val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
2951 W_REG(sii->osh, reg16, val16);
2954 /* restore the original index */
2955 si_setcoreidx(&sii->pub, origidx);
2957 pcicore_hwup(sii->pch);
2958 return 0;
2961 #if defined(BCMDBG)
2962 #endif
2964 /* change logical "focus" to the gpio core for optimized access */
2965 void *
2966 si_gpiosetcore(si_t *sih)
2968 return (si_setcoreidx(sih, SI_CC_IDX));
2972 * mask & set gpiocontrol bits.
2973 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
2974 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
2975 * to some chip-specific purpose.
2977 uint32
2978 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2980 uint regoff;
2982 regoff = 0;
2984 /* gpios could be shared on router platforms
2985 * ignore reservation if it's high priority (e.g., test apps)
2987 if ((priority != GPIO_HI_PRIORITY) &&
2988 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2989 mask = priority ? (si_gpioreservation & mask) :
2990 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2991 val &= mask;
2994 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2995 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2998 /* mask&set gpio output enable bits */
2999 uint32
3000 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3002 uint regoff;
3004 regoff = 0;
3006 /* gpios could be shared on router platforms
3007 * ignore reservation if it's high priority (e.g., test apps)
3009 if ((priority != GPIO_HI_PRIORITY) &&
3010 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3011 mask = priority ? (si_gpioreservation & mask) :
3012 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3013 val &= mask;
3016 regoff = OFFSETOF(chipcregs_t, gpioouten);
3017 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3020 /* mask&set gpio output bits */
3021 uint32
3022 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3024 uint regoff;
3026 regoff = 0;
3028 /* gpios could be shared on router platforms
3029 * ignore reservation if it's high priority (e.g., test apps)
3031 if ((priority != GPIO_HI_PRIORITY) &&
3032 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3033 mask = priority ? (si_gpioreservation & mask) :
3034 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3035 val &= mask;
3038 regoff = OFFSETOF(chipcregs_t, gpioout);
3039 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3042 /* reserve one gpio */
3043 uint32
3044 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3046 /* only cores on SI_BUS share GPIO's and only applcation users need to
3047 * reserve/release GPIO
3049 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3050 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3051 return 0xffffffff;
3053 /* make sure only one bit is set */
3054 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3055 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3056 return 0xffffffff;
3059 /* already reserved */
3060 if (si_gpioreservation & gpio_bitmask)
3061 return 0xffffffff;
3062 /* set reservation */
3063 si_gpioreservation |= gpio_bitmask;
3065 return si_gpioreservation;
3068 /* release one gpio */
3070 * releasing the gpio doesn't change the current value on the GPIO last write value
3071 * persists till some one overwrites it
3074 uint32
3075 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3077 /* only cores on SI_BUS share GPIO's and only applcation users need to
3078 * reserve/release GPIO
3080 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3081 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3082 return 0xffffffff;
3084 /* make sure only one bit is set */
3085 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3086 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3087 return 0xffffffff;
3090 /* already released */
3091 if (!(si_gpioreservation & gpio_bitmask))
3092 return 0xffffffff;
3094 /* clear reservation */
3095 si_gpioreservation &= ~gpio_bitmask;
3097 return si_gpioreservation;
3100 /* return the current gpioin register value */
3101 uint32
3102 si_gpioin(si_t *sih)
3104 uint regoff;
3106 regoff = OFFSETOF(chipcregs_t, gpioin);
3107 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
3110 /* mask&set gpio interrupt polarity bits */
3111 uint32
3112 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3114 uint regoff;
3116 /* gpios could be shared on router platforms */
3117 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3118 mask = priority ? (si_gpioreservation & mask) :
3119 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3120 val &= mask;
3123 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
3124 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3127 /* mask&set gpio interrupt mask bits */
3128 uint32
3129 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3131 uint regoff;
3133 /* gpios could be shared on router platforms */
3134 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3135 mask = priority ? (si_gpioreservation & mask) :
3136 ((si_gpioreservation | mask) & ~(si_gpioreservation));
3137 val &= mask;
3140 regoff = OFFSETOF(chipcregs_t, gpiointmask);
3141 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3144 /* assign the gpio to an led */
3145 uint32
3146 si_gpioled(si_t *sih, uint32 mask, uint32 val)
3148 if (sih->ccrev < 16)
3149 return 0xffffffff;
3151 /* gpio led powersave reg */
3152 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
3155 /* mask&set gpio timer val */
3156 uint32
3157 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
3159 if (sih->ccrev < 16)
3160 return 0xffffffff;
3162 return (si_corereg(sih, SI_CC_IDX,
3163 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
3166 uint32
3167 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
3169 uint offs;
3171 if (sih->ccrev < 20)
3172 return 0xffffffff;
3174 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
3175 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3178 uint32
3179 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
3181 uint offs;
3183 if (sih->ccrev < 11)
3184 return 0xffffffff;
3186 if (regtype == GPIO_REGEVT)
3187 offs = OFFSETOF(chipcregs_t, gpioevent);
3188 else if (regtype == GPIO_REGEVT_INTMSK)
3189 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
3190 else if (regtype == GPIO_REGEVT_INTPOL)
3191 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
3192 else
3193 return 0xffffffff;
3195 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
3198 void *
3199 BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event,
3200 bool level, gpio_handler_t cb, void *arg)
3202 si_info_t *sii;
3203 gpioh_item_t *gi;
3205 ASSERT(event);
3206 ASSERT(cb != NULL);
3208 sii = SI_INFO(sih);
3209 if (sih->ccrev < 11)
3210 return NULL;
3212 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
3213 return NULL;
3215 bzero(gi, sizeof(gpioh_item_t));
3216 gi->event = event;
3217 gi->handler = cb;
3218 gi->arg = arg;
3219 gi->level = level;
3221 gi->next = sii->gpioh_head;
3222 sii->gpioh_head = gi;
3224 #ifdef BCMDBG_ERR
3226 gpioh_item_t *h = sii->gpioh_head;
3227 int cnt = 0;
3229 for (; h; h = h->next) {
3230 cnt++;
3231 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3232 h, h->handler, h->event));
3234 SI_ERROR(("gpiohdler total=%d\n", cnt));
3236 #endif
3237 return (void *)(gi);
3240 void
3241 BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh)
3243 si_info_t *sii;
3244 gpioh_item_t *p, *n;
3246 sii = SI_INFO(sih);
3247 if (sih->ccrev < 11)
3248 return;
3250 ASSERT(sii->gpioh_head != NULL);
3251 if ((void*)sii->gpioh_head == gpioh) {
3252 sii->gpioh_head = sii->gpioh_head->next;
3253 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3254 return;
3255 } else {
3256 p = sii->gpioh_head;
3257 n = p->next;
3258 while (n) {
3259 if ((void*)n == gpioh) {
3260 p->next = n->next;
3261 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3262 return;
3264 p = n;
3265 n = n->next;
3269 #ifdef BCMDBG_ERR
3271 gpioh_item_t *h = sii->gpioh_head;
3272 int cnt = 0;
3274 for (; h; h = h->next) {
3275 cnt++;
3276 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3277 h, h->handler, h->event));
3279 SI_ERROR(("gpiohdler total=%d\n", cnt));
3281 #endif
3282 ASSERT(0); /* Not found in list */
3285 void
3286 si_gpio_handler_process(si_t *sih)
3288 si_info_t *sii;
3289 gpioh_item_t *h;
3290 uint32 level = si_gpioin(sih);
3291 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
3292 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
3293 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
3295 sii = SI_INFO(sih);
3296 for (h = sii->gpioh_head; h != NULL; h = h->next) {
3297 if (h->handler) {
3298 uint32 status = (h->level ? level : edge) & h->event;
3299 uint32 polarity = (h->level ? levelp : edgep) & h->event;
3301 /* polarity bitval is opposite of status bitval */
3302 if (status ^ polarity)
3303 h->handler(status, h->arg);
3307 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
3310 uint32
3311 si_gpio_int_enable(si_t *sih, bool enable)
3313 uint offs;
3315 if (sih->ccrev < 11)
3316 return 0xffffffff;
3318 offs = OFFSETOF(chipcregs_t, intmask);
3319 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
3323 /* Return the size of the specified SOCRAM bank */
3324 static uint
3325 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
3327 uint banksize, bankinfo;
3328 uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3330 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
3332 W_REG(sii->osh, &regs->bankidx, bankidx);
3333 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3334 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
3335 return banksize;
3338 void
3339 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
3341 si_info_t *sii;
3342 uint origidx;
3343 uint intr_val = 0;
3344 sbsocramregs_t *regs;
3345 bool wasup;
3346 uint corerev;
3348 sii = SI_INFO(sih);
3350 /* Block ints and save current core */
3351 INTR_OFF(sii, intr_val);
3352 origidx = si_coreidx(sih);
3354 if (!set)
3355 *enable = *protect = *remap = 0;
3357 /* Switch to SOCRAM core */
3358 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3359 goto done;
3361 /* Get info for determining size */
3362 if (!(wasup = si_iscoreup(sih)))
3363 si_core_reset(sih, 0, 0);
3365 corerev = si_corerev(sih);
3366 if (corerev >= 10) {
3367 uint32 extcinfo;
3368 uint8 nb;
3369 uint8 i;
3370 uint32 bankidx, bankinfo;
3372 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3373 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3374 for (i = 0; i < nb; i++) {
3375 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3376 W_REG(sii->osh, &regs->bankidx, bankidx);
3377 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3378 if (set) {
3379 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
3380 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
3381 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
3382 if (*enable) {
3383 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
3384 if (*protect)
3385 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
3386 if ((corerev >= 16) && *remap)
3387 bankinfo |=
3388 (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
3390 W_REG(sii->osh, &regs->bankinfo, bankinfo);
3392 else if (i == 0) {
3393 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
3394 *enable = 1;
3395 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
3396 *protect = 1;
3397 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
3398 *remap = 1;
3404 /* Return to previous state and core */
3405 if (!wasup)
3406 si_core_disable(sih, 0);
3407 si_setcoreidx(sih, origidx);
3409 done:
3410 INTR_RESTORE(sii, intr_val);
3413 bool
3414 si_socdevram_remap_isenb(si_t *sih)
3416 si_info_t *sii;
3417 uint origidx;
3418 uint intr_val = 0;
3419 sbsocramregs_t *regs;
3420 bool wasup, remap = FALSE;
3421 uint corerev;
3422 uint32 extcinfo;
3423 uint8 nb;
3424 uint8 i;
3425 uint32 bankidx, bankinfo;
3427 sii = SI_INFO(sih);
3429 /* Block ints and save current core */
3430 INTR_OFF(sii, intr_val);
3431 origidx = si_coreidx(sih);
3433 /* Switch to SOCRAM core */
3434 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3435 goto done;
3437 /* Get info for determining size */
3438 if (!(wasup = si_iscoreup(sih)))
3439 si_core_reset(sih, 0, 0);
3441 corerev = si_corerev(sih);
3442 if (corerev >= 16) {
3443 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3444 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3445 for (i = 0; i < nb; i++) {
3446 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3447 W_REG(sii->osh, &regs->bankidx, bankidx);
3448 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3449 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
3450 remap = TRUE;
3451 break;
3456 /* Return to previous state and core */
3457 if (!wasup)
3458 si_core_disable(sih, 0);
3459 si_setcoreidx(sih, origidx);
3461 done:
3462 INTR_RESTORE(sii, intr_val);
3463 return remap;
3466 bool
3467 si_socdevram_pkg(si_t *sih)
3469 if (si_socdevram_size(sih) > 0)
3470 return TRUE;
3471 else
3472 return FALSE;
3475 uint32
3476 si_socdevram_size(si_t *sih)
3478 si_info_t *sii;
3479 uint origidx;
3480 uint intr_val = 0;
3481 uint32 memsize = 0;
3482 sbsocramregs_t *regs;
3483 bool wasup;
3484 uint corerev;
3486 sii = SI_INFO(sih);
3488 /* Block ints and save current core */
3489 INTR_OFF(sii, intr_val);
3490 origidx = si_coreidx(sih);
3492 /* Switch to SOCRAM core */
3493 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3494 goto done;
3496 /* Get info for determining size */
3497 if (!(wasup = si_iscoreup(sih)))
3498 si_core_reset(sih, 0, 0);
3500 corerev = si_corerev(sih);
3501 if (corerev >= 10) {
3502 uint32 extcinfo;
3503 uint8 nb;
3504 uint8 i;
3506 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3507 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3508 for (i = 0; i < nb; i++)
3509 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3512 /* Return to previous state and core */
3513 if (!wasup)
3514 si_core_disable(sih, 0);
3515 si_setcoreidx(sih, origidx);
3517 done:
3518 INTR_RESTORE(sii, intr_val);
3520 return memsize;
3523 uint32
3524 si_socdevram_remap_size(si_t *sih)
3526 si_info_t *sii;
3527 uint origidx;
3528 uint intr_val = 0;
3529 uint32 memsize = 0, banksz;
3530 sbsocramregs_t *regs;
3531 bool wasup;
3532 uint corerev;
3533 uint32 extcinfo;
3534 uint8 nb;
3535 uint8 i;
3536 uint32 bankidx, bankinfo;
3538 sii = SI_INFO(sih);
3540 /* Block ints and save current core */
3541 INTR_OFF(sii, intr_val);
3542 origidx = si_coreidx(sih);
3544 /* Switch to SOCRAM core */
3545 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3546 goto done;
3548 /* Get info for determining size */
3549 if (!(wasup = si_iscoreup(sih)))
3550 si_core_reset(sih, 0, 0);
3552 corerev = si_corerev(sih);
3553 if (corerev >= 16) {
3554 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3555 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3558 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
3559 * Only four banks are accessible to ARM
3561 if ((corerev == 16) && (nb == 5))
3562 nb = 4;
3564 for (i = 0; i < nb; i++) {
3565 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3566 W_REG(sii->osh, &regs->bankidx, bankidx);
3567 bankinfo = R_REG(sii->osh, &regs->bankinfo);
3568 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
3569 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3570 memsize += banksz;
3571 } else {
3572 /* Account only consecutive banks for now */
3573 break;
3578 /* Return to previous state and core */
3579 if (!wasup)
3580 si_core_disable(sih, 0);
3581 si_setcoreidx(sih, origidx);
3583 done:
3584 INTR_RESTORE(sii, intr_val);
3586 return memsize;
3589 /* Return the RAM size of the SOCRAM core */
3590 uint32
3591 si_socram_size(si_t *sih)
3593 si_info_t *sii;
3594 uint origidx;
3595 uint intr_val = 0;
3597 sbsocramregs_t *regs;
3598 bool wasup;
3599 uint corerev;
3600 uint32 coreinfo;
3601 uint memsize = 0;
3603 sii = SI_INFO(sih);
3605 /* Block ints and save current core */
3606 INTR_OFF(sii, intr_val);
3607 origidx = si_coreidx(sih);
3609 /* Switch to SOCRAM core */
3610 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3611 goto done;
3613 /* Get info for determining size */
3614 if (!(wasup = si_iscoreup(sih)))
3615 si_core_reset(sih, 0, 0);
3616 corerev = si_corerev(sih);
3617 coreinfo = R_REG(sii->osh, &regs->coreinfo);
3619 /* Calculate size from coreinfo based on rev */
3620 if (corerev == 0)
3621 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
3622 else if (corerev < 3) {
3623 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
3624 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3625 } else if ((corerev <= 7) || (corerev == 12)) {
3626 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3627 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
3628 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
3629 if (lss != 0)
3630 nb --;
3631 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
3632 if (lss != 0)
3633 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
3634 } else {
3635 uint8 i;
3636 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3637 for (i = 0; i < nb; i++)
3638 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
3641 /* Return to previous state and core */
3642 if (!wasup)
3643 si_core_disable(sih, 0);
3644 si_setcoreidx(sih, origidx);
3646 done:
3647 INTR_RESTORE(sii, intr_val);
3649 return memsize;
3653 #ifdef BCMECICOEX
3654 #define NOTIFY_BT_FM_DISABLE(sih, val) \
3655 si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
3656 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
3658 /* Query OTP to see if FM is disabled */
3659 static int
3660 BCMINITFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled)
3662 int error = BCME_OK;
3663 uint bitoff = 0;
3664 bool wasup;
3665 void *oh;
3667 /* Determine the bit for the chip */
3668 switch (CHIPID(sih->chip)) {
3669 case BCM4325_CHIP_ID:
3670 if (CHIPREV(sih->chiprev) >= 6)
3671 bitoff = OTP4325_FM_DISABLED_OFFSET;
3672 break;
3673 default:
3674 break;
3677 /* If there is a bit for this chip, check it */
3678 if (bitoff) {
3679 if (!(wasup = si_is_otp_powered(sih))) {
3680 si_otp_power(sih, TRUE);
3683 if ((oh = otp_init(sih)) != NULL)
3684 *FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET);
3685 else
3686 error = BCME_NOTFOUND;
3688 if (!wasup) {
3689 si_otp_power(sih, FALSE);
3693 return error;
3696 bool
3697 si_eci(si_t *sih)
3699 return (!!(sih->cccaps & CC_CAP_ECI));
3702 bool
3703 si_seci(si_t *sih)
3705 return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT);
3708 /* ECI Init routine */
3710 BCMINITFN(si_eci_init)(si_t *sih)
3712 uint32 origidx = 0;
3713 si_info_t *sii;
3714 chipcregs_t *cc;
3715 bool fast;
3716 uint16 FMDisabled = FALSE;
3718 /* check for ECI capability */
3719 if (!(sih->cccaps & CC_CAP_ECI))
3720 return BCME_ERROR;
3722 sii = SI_INFO(sih);
3723 fast = SI_FAST(sii);
3724 if (!fast) {
3725 origidx = sii->curidx;
3726 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3727 return BCME_ERROR;
3728 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3729 return BCME_ERROR;
3730 ASSERT(cc);
3732 /* disable level based interrupts */
3733 if (sih->ccrev < 35) {
3734 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0);
3735 W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0);
3736 W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0);
3738 else {
3739 W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0);
3740 W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0);
3743 /* Assign eci_output bits between 'wl' and dot11mac */
3744 if (sih->ccrev < 35) {
3745 W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS);
3747 else {
3748 W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS);
3749 W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS);
3752 /* enable only edge based interrupts
3753 * only toggle on bit 62 triggers an interrupt
3755 if (sih->ccrev < 35) {
3756 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0);
3757 W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0);
3758 W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0);
3760 else {
3761 W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0);
3762 W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0);
3765 /* restore previous core */
3766 if (!fast)
3767 si_setcoreidx(sih, origidx);
3769 /* if FM disabled in OTP, let BT know */
3770 if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) {
3771 if (FMDisabled) {
3772 NOTIFY_BT_FM_DISABLE(sih, 1);
3776 return 0;
3780 * Write values to BT on eci_output.
3782 void
3783 si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt)
3785 uint32 offset;
3787 /* Nothing to do if there is no eci */
3788 if ((sih->cccaps & CC_CAP_ECI) == 0)
3789 return;
3791 /* Clear interrupt bit by default */
3792 if (interrupt)
3793 si_corereg(sih, SI_CC_IDX,
3794 (sih->ccrev < 35 ?
3795 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3796 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3797 (1 << 30), 0);
3799 if (sih->ccrev >= 35) {
3800 if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
3801 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi);
3802 mask = mask & ~0xFFFF0000;
3804 else {
3805 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo);
3806 mask = mask | (1<<30);
3807 val = val & ~(1 << 30);
3810 else {
3811 offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output);
3812 val = val & ~(1 << 30);
3815 si_corereg(sih, SI_CC_IDX, offset, mask, val);
3817 /* Set interrupt bit if needed */
3818 if (interrupt)
3819 si_corereg(sih, SI_CC_IDX,
3820 (sih->ccrev < 35 ?
3821 OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3822 OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3823 (1 << 30), (1 << 30));
3826 /* seci clock enable/disable */
3827 static void
3828 si_seci_clkreq(si_t *sih, bool enable)
3830 uint32 clk_ctl_st;
3831 uint32 offset;
3832 uint32 val;
3834 if (!si_seci(sih))
3835 return;
3837 if (enable)
3838 val = CLKCTL_STS_SECI_CLK_REQ;
3839 else
3840 val = 0;
3842 offset = OFFSETOF(chipcregs_t, clk_ctl_st);
3844 si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val);
3846 if (!enable)
3847 return;
3849 SPINWAIT(!(si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL),
3850 PMU_MAX_TRANSITION_DLY);
3852 clk_ctl_st = si_corereg(sih, 0, offset, 0, 0);
3853 if (enable) {
3854 if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) {
3855 SI_ERROR(("SECI clock is still not available\n"));
3856 return;
3861 void
3862 BCMINITFN(si_seci_down)(si_t *sih)
3864 uint32 origidx = 0;
3865 si_info_t *sii;
3866 chipcregs_t *cc;
3867 bool fast;
3868 uint32 seci_conf;
3870 if (!si_seci(sih))
3871 return;
3873 sii = SI_INFO(sih);
3874 fast = SI_FAST(sii);
3876 if (!fast) {
3877 origidx = sii->curidx;
3878 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3879 return;
3880 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3881 return;
3882 ASSERT(cc);
3883 /* 4331 X28 sign off seci */
3884 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3885 /* flush seci */
3886 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3887 seci_conf |= SECI_UPD_SECI;
3888 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3889 SPINWAIT((R_REG(sii->osh, &cc->SECI_config) & SECI_UPD_SECI), 1000);
3891 /* SECI sign off */
3892 W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_0);
3893 W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_1);
3894 SPINWAIT((R_REG(sii->osh, &cc->seci_uart_lsr) & (1 << 2)), 1000);
3895 /* put seci in reset */
3896 seci_conf = R_REG(sii->osh, &cc->SECI_config);
3897 seci_conf &= ~SECI_ENAB_SECI_ECI;
3898 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3899 seci_conf |= SECI_RESET;
3900 W_REG(sii->osh, &cc->SECI_config, seci_conf);
3903 /* bring down the clock if up */
3904 si_seci_clkreq(sih, FALSE);
3906 /* restore previous core */
3907 if (!fast)
3908 si_setcoreidx(sih, origidx);
3911 void
3912 si_seci_upd(si_t *sih, bool enable)
3914 uint32 origidx = 0;
3915 si_info_t *sii;
3916 chipcregs_t *cc;
3917 bool fast;
3918 uint32 regval;
3919 uint intr_val = 0;
3921 if (!si_seci(sih))
3922 return;
3924 sii = SI_INFO(sih);
3925 fast = SI_FAST(sii);
3926 INTR_OFF(sii, intr_val);
3927 if (!fast) {
3928 origidx = sii->curidx;
3929 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3930 goto exit;
3931 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3932 goto exit;
3934 ASSERT(cc);
3936 /* 4331 Select SECI based on enable input */
3937 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3938 regval = R_REG(sii->osh, &cc->chipcontrol);
3939 if (enable)
3940 regval |= CCTRL4331_SECI;
3941 else
3942 regval &= ~CCTRL4331_SECI;
3943 W_REG(sii->osh, &cc->chipcontrol, regval);
3945 exit:
3946 /* restore previous core */
3947 if (!fast)
3948 si_setcoreidx(sih, origidx);
3950 INTR_RESTORE(sii, intr_val);
3953 /* SECI Init routine, pass in seci_mode */
3954 void *
3955 BCMINITFN(si_seci_init)(si_t *sih, uint8 seci_mode)
3957 uint32 origidx = 0;
3958 uint32 offset;
3959 si_info_t *sii;
3960 void *ptr;
3961 chipcregs_t *cc;
3962 bool fast;
3963 uint32 seci_conf;
3964 uint32 regval;
3966 if (sih->ccrev < 35)
3967 return NULL;
3969 if (!si_seci(sih))
3970 return NULL;
3972 if (seci_mode > SECI_MODE_MASK)
3973 return NULL;
3975 sii = SI_INFO(sih);
3976 fast = SI_FAST(sii);
3977 if (!fast) {
3978 origidx = sii->curidx;
3979 if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3980 return NULL;
3981 } else if ((ptr = CCREGS_FAST(sii)) == NULL)
3982 return NULL;
3983 cc = (chipcregs_t *)ptr;
3984 ASSERT(cc);
3987 /* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
3988 if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
3989 CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3990 regval = R_REG(sii->osh, &cc->chipcontrol);
3991 regval |= CCTRL4331_SECI;
3992 W_REG(sii->osh, &cc->chipcontrol, regval);
3996 if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
3997 (0)) {
3998 regval = R_REG(sii->osh, &cc->jtagctrl);
3999 regval |= 0x1;
4000 W_REG(sii->osh, &cc->jtagctrl, regval);
4003 /* enable SECI clock */
4004 si_seci_clkreq(sih, TRUE);
4006 /* put the SECI in reset */
4007 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4008 seci_conf &= ~SECI_ENAB_SECI_ECI;
4009 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4010 seci_conf = SECI_RESET;
4011 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4013 /* set force-low, and set EN_SECI for all non-legacy modes */
4014 seci_conf |= SECI_ENAB_SECIOUT_DIS;
4015 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
4016 (seci_mode == SECI_MODE_HALF_SECI))
4018 seci_conf |= SECI_ENAB_SECI_ECI;
4020 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4022 /* take seci out of reset */
4023 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4024 seci_conf &= ~(SECI_RESET);
4025 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4027 /* set UART/SECI baud rate */
4028 /* hard-coded at 4MBaud for now */
4029 if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
4030 (seci_mode == SECI_MODE_HALF_SECI)) {
4031 offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
4032 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF); /* 4MBaud */
4033 offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
4034 if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
4035 (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
4036 (0)) {
4037 /* 43236 ccrev = 36 and MAC clk = 96MHz */
4038 /* 4331,43143 MAC clk = 96MHz */
4039 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
4041 else {
4042 /* 4336 MAC clk is 80MHz */
4043 si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22);
4046 /* LCR/MCR settings */
4047 offset = OFFSETOF(chipcregs_t, seci_uart_lcr);
4048 si_corereg(sih, SI_CC_IDX, offset, 0xFF,
4049 (SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */
4050 offset = OFFSETOF(chipcregs_t, seci_uart_mcr);
4051 si_corereg(sih, SI_CC_IDX, offset,
4052 0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */
4054 /* Give control of ECI output regs to MAC core */
4055 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo);
4056 si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS);
4057 offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi);
4058 si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS);
4061 /* set the seci mode in seci conf register */
4062 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4063 seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT);
4064 seci_conf |= (seci_mode << SECI_MODE_SHIFT);
4065 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4067 /* Clear force-low bit */
4068 seci_conf = R_REG(sii->osh, &cc->SECI_config);
4069 seci_conf &= ~SECI_ENAB_SECIOUT_DIS;
4070 W_REG(sii->osh, &cc->SECI_config, seci_conf);
4072 /* restore previous core */
4073 if (!fast)
4074 si_setcoreidx(sih, origidx);
4076 return ptr;
4078 #endif /* BCMECICOEX */
4080 void
4081 si_btcgpiowar(si_t *sih)
4083 si_info_t *sii;
4084 uint origidx;
4085 uint intr_val = 0;
4086 chipcregs_t *cc;
4088 sii = SI_INFO(sih);
4090 /* Make sure that there is ChipCommon core present &&
4091 * UART_TX is strapped to 1
4093 if (!(sih->cccaps & CC_CAP_UARTGPIO))
4094 return;
4096 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
4097 INTR_OFF(sii, intr_val);
4099 origidx = si_coreidx(sih);
4101 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4102 ASSERT(cc != NULL);
4104 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
4106 /* restore the original index */
4107 si_setcoreidx(sih, origidx);
4109 INTR_RESTORE(sii, intr_val);
4112 void
4113 si_chipcontrl_btshd0_4331(si_t *sih, bool on)
4115 si_info_t *sii;
4116 chipcregs_t *cc;
4117 uint origidx;
4118 uint32 val;
4119 uint intr_val = 0;
4121 sii = SI_INFO(sih);
4123 INTR_OFF(sii, intr_val);
4125 origidx = si_coreidx(sih);
4127 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4129 val = R_REG(sii->osh, &cc->chipcontrol);
4131 /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
4132 if (on) {
4133 /* Enable bt_shd0 on gpio4: */
4134 val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
4135 W_REG(sii->osh, &cc->chipcontrol, val);
4136 } else {
4137 val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
4138 W_REG(sii->osh, &cc->chipcontrol, val);
4141 /* restore the original index */
4142 si_setcoreidx(sih, origidx);
4144 INTR_RESTORE(sii, intr_val);
4147 void
4148 si_chipcontrl_restore(si_t *sih, uint32 val)
4150 si_info_t *sii;
4151 chipcregs_t *cc;
4152 uint origidx;
4154 sii = SI_INFO(sih);
4155 origidx = si_coreidx(sih);
4156 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4157 W_REG(sii->osh, &cc->chipcontrol, val);
4158 si_setcoreidx(sih, origidx);
4161 uint32
4162 si_chipcontrl_read(si_t *sih)
4164 si_info_t *sii;
4165 chipcregs_t *cc;
4166 uint origidx;
4167 uint32 val;
4169 sii = SI_INFO(sih);
4170 origidx = si_coreidx(sih);
4171 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4172 val = R_REG(sii->osh, &cc->chipcontrol);
4173 si_setcoreidx(sih, origidx);
4174 return val;
4177 void
4178 si_chipcontrl_epa4331(si_t *sih, bool on)
4180 si_info_t *sii;
4181 chipcregs_t *cc;
4182 uint origidx;
4183 uint32 val;
4185 sii = SI_INFO(sih);
4186 origidx = si_coreidx(sih);
4188 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4190 val = R_REG(sii->osh, &cc->chipcontrol);
4192 if (on) {
4193 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
4194 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
4195 /* Ext PA Controls for 4331 12x9 Package */
4196 W_REG(sii->osh, &cc->chipcontrol, val);
4197 } else {
4198 /* Ext PA Controls for 4331 12x12 Package */
4199 if (sih->chiprev > 0) {
4200 W_REG(sii->osh, &cc->chipcontrol, val |
4201 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
4202 } else {
4203 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
4206 } else {
4207 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
4208 W_REG(sii->osh, &cc->chipcontrol, val);
4211 si_setcoreidx(sih, origidx);
4214 /* switch muxed pins, on: SROM, off: FEMCTRL */
4215 void
4216 si_chipcontrl_srom4360(si_t *sih, bool on)
4218 si_info_t *sii;
4219 chipcregs_t *cc;
4220 uint origidx;
4221 uint32 val;
4223 sii = SI_INFO(sih);
4224 origidx = si_coreidx(sih);
4226 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4228 val = R_REG(sii->osh, &cc->chipcontrol);
4230 if (on) {
4231 val &= ~(CCTRL4360_SECI_MODE |
4232 CCTRL4360_BTSWCTRL_MODE |
4233 CCTRL4360_EXTRA_FEMCTRL_MODE |
4234 CCTRL4360_BT_LGCY_MODE |
4235 CCTRL4360_CORE2FEMCTRL4_ON);
4237 W_REG(sii->osh, &cc->chipcontrol, val);
4238 } else {
4241 si_setcoreidx(sih, origidx);
4244 void
4245 si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
4247 si_info_t *sii;
4248 chipcregs_t *cc;
4249 uint origidx;
4250 uint32 val;
4251 bool sel_chip;
4253 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
4254 (CHIPID(sih->chip) == BCM43431_CHIP_ID);
4255 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
4257 if (!sel_chip)
4258 return;
4260 sii = SI_INFO(sih);
4261 origidx = si_coreidx(sih);
4263 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4265 val = R_REG(sii->osh, &cc->chipcontrol);
4267 if (enter_wowl) {
4268 val |= CCTRL4331_EXTPA_EN;
4269 W_REG(sii->osh, &cc->chipcontrol, val);
4270 } else {
4271 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
4272 W_REG(sii->osh, &cc->chipcontrol, val);
4274 si_setcoreidx(sih, origidx);
4277 uint
4278 si_pll_reset(si_t *sih)
4280 uint err = 0;
4282 uint intr_val = 0;
4283 si_info_t *sii;
4284 sii = SI_INFO(sih);
4285 INTR_OFF(sii, intr_val);
4286 err = si_pll_minresmask_reset(sih, sii->osh);
4287 INTR_RESTORE(sii, intr_val);
4288 return (err);
4291 /* Enable BT-COEX & Ex-PA for 4313 */
4292 void
4293 si_epa_4313war(si_t *sih)
4295 si_info_t *sii;
4296 chipcregs_t *cc;
4297 uint origidx;
4299 sii = SI_INFO(sih);
4300 origidx = si_coreidx(sih);
4302 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4304 /* EPA Fix */
4305 W_REG(sii->osh, &cc->gpiocontrol,
4306 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
4308 si_setcoreidx(sih, origidx);
4311 void
4312 si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
4314 si_info_t *sii;
4315 sii = SI_INFO(sih);
4317 si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear);
4320 /* WL/BT control for 4313 btcombo boards >= P250 */
4321 void
4322 si_btcombo_p250_4313_war(si_t *sih)
4324 si_info_t *sii;
4325 chipcregs_t *cc;
4326 uint origidx;
4328 sii = SI_INFO(sih);
4329 origidx = si_coreidx(sih);
4331 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4332 W_REG(sii->osh, &cc->gpiocontrol,
4333 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
4335 W_REG(sii->osh, &cc->gpioouten,
4336 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
4338 si_setcoreidx(sih, origidx);
4340 void
4341 si_btc_enable_chipcontrol(si_t *sih)
4343 si_info_t *sii;
4344 chipcregs_t *cc;
4345 uint origidx;
4347 sii = SI_INFO(sih);
4348 origidx = si_coreidx(sih);
4350 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4352 /* BT fix */
4353 W_REG(sii->osh, &cc->chipcontrol,
4354 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
4356 si_setcoreidx(sih, origidx);
4358 void
4359 si_btcombo_43228_war(si_t *sih)
4361 si_info_t *sii;
4362 chipcregs_t *cc;
4363 uint origidx;
4365 sii = SI_INFO(sih);
4366 origidx = si_coreidx(sih);
4368 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
4370 W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
4371 W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
4373 si_setcoreidx(sih, origidx);
4376 /* check if the device is removed */
4377 bool
4378 si_deviceremoved(si_t *sih)
4380 uint32 w;
4381 si_info_t *sii;
4383 sii = SI_INFO(sih);
4385 switch (BUSTYPE(sih->bustype)) {
4386 case PCI_BUS:
4387 ASSERT(sii->osh != NULL);
4388 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
4389 if ((w & 0xFFFF) != VENDOR_BROADCOM)
4390 return TRUE;
4391 break;
4393 return FALSE;
4396 bool
4397 si_is_sprom_available(si_t *sih)
4399 if (sih->ccrev >= 31) {
4400 si_info_t *sii;
4401 uint origidx;
4402 chipcregs_t *cc;
4403 uint32 sromctrl;
4405 if ((sih->cccaps & CC_CAP_SROM) == 0)
4406 return FALSE;
4408 sii = SI_INFO(sih);
4409 origidx = sii->curidx;
4410 cc = si_setcoreidx(sih, SI_CC_IDX);
4411 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
4412 si_setcoreidx(sih, origidx);
4413 return (sromctrl & SRC_PRESENT);
4416 switch (CHIPID(sih->chip)) {
4417 case BCM4312_CHIP_ID:
4418 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
4419 case BCM4325_CHIP_ID:
4420 return (sih->chipst & CST4325_SPROM_SEL) != 0;
4421 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4422 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
4423 case BCM4342_CHIP_ID: {
4424 uint32 spromotp;
4425 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4426 CST4322_SPROM_OTP_SEL_SHIFT;
4427 return (spromotp & CST4322_SPROM_PRESENT) != 0;
4429 case BCM4329_CHIP_ID:
4430 return (sih->chipst & CST4329_SPROM_SEL) != 0;
4431 case BCM4315_CHIP_ID:
4432 return (sih->chipst & CST4315_SPROM_SEL) != 0;
4433 case BCM4319_CHIP_ID:
4434 return (sih->chipst & CST4319_SPROM_SEL) != 0;
4435 case BCM4336_CHIP_ID:
4436 case BCM43362_CHIP_ID:
4437 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
4438 case BCM4330_CHIP_ID:
4439 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
4440 case BCM4313_CHIP_ID:
4441 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
4442 case BCM4331_CHIP_ID:
4443 case BCM43431_CHIP_ID:
4444 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
4445 case BCM43239_CHIP_ID:
4446 return ((sih->chipst & CST43239_SPROM_MASK) &&
4447 !(sih->chipst & CST43239_SFLASH_MASK));
4448 case BCM4324_CHIP_ID:
4449 return ((sih->chipst & CST4324_SPROM_MASK) &&
4450 !(sih->chipst & CST4324_SFLASH_MASK));
4451 case BCM4335_CHIP_ID:
4452 return ((sih->chipst & CST4335_SPROM_MASK) &&
4453 !(sih->chipst & CST4335_SFLASH_MASK));
4454 case BCM43131_CHIP_ID:
4455 case BCM43217_CHIP_ID:
4456 case BCM43227_CHIP_ID:
4457 case BCM43228_CHIP_ID:
4458 case BCM43428_CHIP_ID:
4459 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
4460 default:
4461 return TRUE;
4465 bool
4466 si_is_otp_disabled(si_t *sih)
4468 switch (CHIPID(sih->chip)) {
4469 case BCM4325_CHIP_ID:
4470 return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN;
4471 case BCM4322_CHIP_ID:
4472 case BCM43221_CHIP_ID:
4473 case BCM43231_CHIP_ID:
4474 case BCM4342_CHIP_ID:
4475 return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4476 CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) !=
4477 CST4322_OTP_PRESENT;
4478 case BCM4329_CHIP_ID:
4479 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN;
4480 case BCM4315_CHIP_ID:
4481 return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN;
4482 case BCM4319_CHIP_ID:
4483 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN;
4484 case BCM4336_CHIP_ID:
4485 case BCM43362_CHIP_ID:
4486 return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
4487 case BCM4330_CHIP_ID:
4488 return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
4489 case BCM43237_CHIP_ID:
4490 return FALSE;
4491 case BCM4313_CHIP_ID:
4492 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
4493 case BCM4331_CHIP_ID:
4494 return (sih->chipst & CST4331_OTP_PRESENT) != CST4331_OTP_PRESENT;
4495 case BCM4360_CHIP_ID:
4496 case BCM43526_CHIP_ID:
4497 case BCM43460_CHIP_ID:
4498 case BCM4352_CHIP_ID:
4499 /* 4360 OTP is always powered and enabled */
4500 return FALSE;
4501 /* These chips always have their OTP on */
4502 case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: case BCM43222_CHIP_ID:
4503 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID:
4504 case BCM43421_CHIP_ID:
4505 case BCM43226_CHIP_ID:
4506 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4507 case BCM43234_CHIP_ID: case BCM43239_CHIP_ID: case BCM4324_CHIP_ID:
4508 case BCM43431_CHIP_ID:
4509 case BCM43131_CHIP_ID:
4510 case BCM43217_CHIP_ID:
4511 case BCM43227_CHIP_ID:
4512 case BCM43228_CHIP_ID:
4513 case BCM43428_CHIP_ID: case BCM4335_CHIP_ID:
4514 default:
4515 return FALSE;
4519 bool
4520 si_is_otp_powered(si_t *sih)
4522 if (PMUCTL_ENAB(sih))
4523 return si_pmu_is_otp_powered(sih, si_osh(sih));
4524 return TRUE;
4527 void
4528 si_otp_power(si_t *sih, bool on)
4530 if (PMUCTL_ENAB(sih))
4531 si_pmu_otp_power(sih, si_osh(sih), on);
4532 OSL_DELAY(1000);
4535 bool
4536 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4537 si_is_sprom_enabled(si_t *sih)
4538 #else
4539 BCMATTACHFN(si_is_sprom_enabled)(si_t *sih)
4540 #endif
4542 if (PMUCTL_ENAB(sih))
4543 return si_pmu_is_sprom_enabled(sih, si_osh(sih));
4544 return TRUE;
4547 void
4548 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4549 si_sprom_enable(si_t *sih, bool enable)
4550 #else
4551 BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable)
4552 #endif
4554 if (PMUCTL_ENAB(sih))
4555 si_pmu_sprom_enable(sih, si_osh(sih), enable);
4558 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
4560 si_cis_source(si_t *sih)
4562 /* Many chips have the same mapping of their chipstatus field */
4563 static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
4564 static const uint cis_43236_sel[] = { CIS_DEFAULT, CIS_OTP };
4566 /* PCI chips use SROM format instead of CIS */
4567 if (BUSTYPE(sih->bustype) == PCI_BUS)
4568 return BCME_NOTFOUND;
4570 switch (CHIPID(sih->chip)) {
4571 case BCM4325_CHIP_ID:
4572 return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4573 CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)];
4574 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4575 case BCM4342_CHIP_ID: {
4576 uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4577 CST4322_SPROM_OTP_SEL_SHIFT;
4579 return ((strap >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[strap]);
4583 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
4584 case BCM43234_CHIP_ID: {
4585 uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >>
4586 CST43236_OTP_SEL_SHIFT;
4587 return ((strap >= ARRAYSIZE(cis_43236_sel)) ? CIS_DEFAULT : cis_43236_sel[strap]);
4590 case BCM4329_CHIP_ID:
4591 return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4592 CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)];
4594 case BCM4315_CHIP_ID:
4596 return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
4597 CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)];
4599 case BCM4319_CHIP_ID: {
4600 uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >>
4601 CST4319_SPROM_OTP_SEL_SHIFT);
4602 return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319];
4604 case BCM4336_CHIP_ID:
4605 case BCM43362_CHIP_ID: {
4606 if (sih->chipst & CST4336_SPROM_PRESENT)
4607 return CIS_SROM;
4608 if (sih->chipst & CST4336_OTP_PRESENT)
4609 return CIS_OTP;
4610 return CIS_DEFAULT;
4612 case BCM4330_CHIP_ID: {
4613 if (sih->chipst & CST4330_SPROM_PRESENT)
4614 return CIS_SROM;
4615 if (sih->chipst & CST4330_OTP_PRESENT)
4616 return CIS_OTP;
4617 return CIS_DEFAULT;
4619 case BCM43239_CHIP_ID: {
4620 if ((sih->chipst & CST43239_SPROM_MASK) && !(sih->chipst & CST43239_SFLASH_MASK))
4621 return CIS_SROM;
4622 return CIS_OTP;
4624 case BCM4324_CHIP_ID:
4626 if ((sih->chipst & CST4324_SPROM_MASK) && !(sih->chipst & CST4324_SFLASH_MASK))
4627 return CIS_SROM;
4628 return CIS_OTP;
4630 case BCM4335_CHIP_ID: {
4631 if ((sih->chipst & CST4335_SPROM_MASK) && !(sih->chipst & CST4335_SFLASH_MASK))
4632 return CIS_SROM;
4633 return CIS_OTP;
4635 case BCM43237_CHIP_ID: {
4636 uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >>
4637 CST43237_OTP_SEL_SHIFT;
4638 return ((strap >= ARRAYSIZE(cis_43236_sel)) ? CIS_DEFAULT : cis_43236_sel[strap]);
4641 case BCM4360_CHIP_ID:
4642 case BCM43526_CHIP_ID: {
4643 if ((sih->chipst & CST4360_OTP_ENABLED))
4644 return CIS_OTP;
4645 return CIS_DEFAULT;
4647 default:
4648 return CIS_DEFAULT;
4652 /* Read/write to OTP to find the FAB manf */
4654 BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw)
4656 int error = BCME_OK;
4657 uint offset = 0;
4658 uint16 data, mask = 0, shift = 0;
4660 switch (CHIPID(sih->chip)) {
4661 case BCM4329_CHIP_ID:
4662 /* Bit locations 133-130 */
4663 if (sih->chiprev >= 3) {
4664 offset = 8;
4665 mask = 0x3c;
4666 shift = 2;
4668 break;
4669 case BCM43362_CHIP_ID:
4670 /* Bit locations 134-130 */
4671 offset = 8;
4672 mask = 0x7c;
4673 shift = 2;
4674 break;
4675 case BCM5356_CHIP_ID:
4676 /* Bit locations 133-130 */
4677 offset = 8;
4678 mask = 0x3c;
4679 shift = 2;
4680 break;
4681 default:
4682 error = BCME_EPERM;
4683 return error;
4686 if (rw == TRUE) {
4687 /* TRUE --> read */
4688 error = otp_read_word(sih, offset, &data);
4689 if (!error)
4690 *fabid = (data & mask) >> shift;
4691 } else {
4692 data = *fabid;
4693 data = (data << shift) & mask;
4694 #ifdef BCMNVRAMW
4695 error = otp_write_word(sih, offset, data);
4696 #endif /* BCMNVRAMW */
4699 return error;
4701 uint16 BCMINITFN(si_fabid)(si_t *sih)
4703 uint32 data;
4704 uint16 fabid = 0;
4706 switch (CHIPID(sih->chip)) {
4707 case BCM4329_CHIP_ID:
4708 case BCM43362_CHIP_ID:
4709 case BCM5356_CHIP_ID:
4710 if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK)
4712 SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));
4714 break;
4716 case BCM4330_CHIP_ID:
4717 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
4718 0, 0);
4719 fabid = ((data & 0xc0000000) >> 30)+((data & 0x20000000) >> 27);
4720 break;
4722 case BCM4334_CHIP_ID:
4723 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid), 0, 0);
4724 fabid = data & 0xf;
4725 break;
4727 case BCM4324_CHIP_ID:
4728 case BCM4335_CHIP_ID:
4729 data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid), 0, 0);
4730 fabid = data & 0xf;
4731 break;
4733 default:
4734 break;
4737 return fabid;
4740 uint32 si_get_sromctl(si_t *sih)
4742 chipcregs_t *cc;
4743 uint origidx;
4744 uint32 sromctl;
4745 osl_t *osh;
4747 osh = si_osh(sih);
4748 origidx = si_coreidx(sih);
4749 cc = si_setcoreidx(sih, SI_CC_IDX);
4750 ASSERT((uintptr)cc);
4752 sromctl = R_REG(osh, &cc->sromcontrol);
4754 /* return to the original core */
4755 si_setcoreidx(sih, origidx);
4756 return sromctl;
4759 int si_set_sromctl(si_t *sih, uint32 value)
4761 chipcregs_t *cc;
4762 uint origidx;
4763 osl_t *osh;
4765 osh = si_osh(sih);
4766 origidx = si_coreidx(sih);
4767 cc = si_setcoreidx(sih, SI_CC_IDX);
4768 ASSERT((uintptr)cc);
4770 /* get chipcommon rev */
4771 if (si_corerev(sih) < 32)
4772 return BCME_UNSUPPORTED;
4774 W_REG(osh, &cc->sromcontrol, value);
4776 /* return to the original core */
4777 si_setcoreidx(sih, origidx);
4778 return BCME_OK;