2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
31 #include <pcie_core.h>
45 #include "siutils_priv.h"
47 /* local prototypes */
48 static si_info_t
*si_doattach(si_info_t
*sii
, uint devid
, osl_t
*osh
, void *regs
,
49 uint bustype
, void *sdh
, char **vars
, uint
*varsz
);
50 static bool si_buscore_prep(si_info_t
*sii
, uint bustype
, uint devid
, void *sdh
);
51 static bool si_buscore_setup(si_info_t
*sii
, chipcregs_t
*cc
, uint bustype
, uint32 savewin
,
52 uint
*origidx
, void *regs
);
53 static void si_nvram_process(si_info_t
*sii
, char *pvars
);
54 #if !defined(_CFE_) || defined(CFG_WL)
55 static void si_sromvars_fixup_4331(si_t
*sih
, char *pvars
);
56 #endif /* !_CFE_ || CFG_WL */
58 /* dev path concatenation util */
59 static char *si_devpathvar(si_t
*sih
, char *var
, int len
, const char *name
);
60 static bool _si_clkctl_cc(si_info_t
*sii
, uint mode
);
61 static bool si_ispcie(si_info_t
*sii
);
62 static uint
BCMINITFN(socram_banksize
)(si_info_t
*sii
, sbsocramregs_t
*r
, uint8 idx
, uint8 mtype
);
65 /* global variable to indicate reservation/release of gpio's */
66 static uint32 si_gpioreservation
= 0;
68 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
71 * Allocate a si handle.
72 * devid - pci device id (used to determine chip#)
73 * osh - opaque OS handle
74 * regs - virtual address of initial core registers
75 * bustype - pci/pcmcia/sb/sdio/etc
76 * vars - pointer to a pointer area for "environment" variables
77 * varsz - pointer to int to return the size of the vars
80 BCMATTACHFN(si_attach
)(uint devid
, osl_t
*osh
, void *regs
,
81 uint bustype
, void *sdh
, char **vars
, uint
*varsz
)
86 if ((sii
= MALLOC(osh
, sizeof (si_info_t
))) == NULL
) {
87 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh
)));
91 if (si_doattach(sii
, devid
, osh
, regs
, bustype
, sdh
, vars
, varsz
) == NULL
) {
92 MFREE(osh
, sii
, sizeof(si_info_t
));
95 sii
->vars
= vars
? *vars
: NULL
;
96 sii
->varsz
= varsz
? *varsz
: 0;
101 /* global kernel resource */
102 static si_info_t ksii
;
104 static uint32 wd_msticks
; /* watchdog timer ticks normalized to ms */
106 /* generic kernel variant of si_attach() */
108 BCMATTACHFN(si_kattach
)(osl_t
*osh
)
110 static bool ksii_attached
= FALSE
;
112 if (!ksii_attached
) {
114 #ifndef SI_ENUM_BASE_VARIABLE
115 regs
= REG_MAP(SI_ENUM_BASE
, SI_CORE_SIZE
);
118 if (si_doattach(&ksii
, BCM4710_DEVICE_ID
, osh
, regs
,
120 osh
!= SI_OSH
? &ksii
.vars
: NULL
,
121 osh
!= SI_OSH
? &ksii
.varsz
: NULL
) == NULL
) {
122 SI_ERROR(("si_kattach: si_doattach failed\n"));
128 /* save ticks normalized to ms for si_watchdog_ms() */
129 if (PMUCTL_ENAB(&ksii
.pub
)) {
130 if (CHIPID(ksii
.pub
.chip
) == BCM4706_CHIP_ID
) {
131 /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
132 wd_msticks
= (si_alp_clock(&ksii
.pub
) / 4) / 1000;
135 /* based on 32KHz ILP clock */
138 if (ksii
.pub
.ccrev
< 18)
139 wd_msticks
= si_clock(&ksii
.pub
) / 1000;
141 wd_msticks
= si_alp_clock(&ksii
.pub
) / 1000;
144 ksii_attached
= TRUE
;
145 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
146 ksii
.pub
.ccrev
, wd_msticks
));
153 si_ldo_war(si_t
*sih
, uint devid
)
155 si_info_t
*sii
= SI_INFO(sih
);
158 void *regs
= sii
->curmap
;
161 rev_id
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_REV
, sizeof(uint32
));
163 if (!(((CHIPID(devid
) == BCM4322_CHIP_ID
) ||
164 (CHIPID(devid
) == BCM4342_CHIP_ID
) ||
165 (CHIPID(devid
) == BCM4322_D11N_ID
) ||
166 (CHIPID(devid
) == BCM4322_D11N2G_ID
) ||
167 (CHIPID(devid
) == BCM4322_D11N5G_ID
)) &&
171 SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid
, rev_id
));
173 /* switch to chipcommon */
174 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_BAR0_WIN
, sizeof(uint32
));
175 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, sizeof(uint32
), SI_ENUM_BASE
);
176 cc
= (chipcregs_t
*)regs
;
178 /* clear bit 7 to fix LDO
179 * write to register *blindly* WITHOUT read since read may timeout
180 * because the default clock is 32k ILP
182 W_REG(sii
->osh
, &cc
->regcontrol_addr
, 0);
183 /* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
184 W_REG(sii
->osh
, &cc
->regcontrol_data
, 0x3001);
188 /* request ALP_AVAIL through PMU to move sb out of ILP */
189 W_REG(sii
->osh
, &cc
->min_res_mask
, 0x0d);
191 SPINWAIT(((ccst
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CLK_CTL_ST
, 4)) & CCS_ALPAVAIL
)
192 == 0, PMU_MAX_TRANSITION_DLY
);
194 if ((ccst
& CCS_ALPAVAIL
) == 0) {
195 SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst
));
198 SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
200 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, sizeof(uint32
), w
);
206 BCMATTACHFN(si_buscore_prep
)(si_info_t
*sii
, uint bustype
, uint devid
, void *sdh
)
208 /* need to set memseg flag for CF card first before any sb registers access */
209 if (BUSTYPE(bustype
) == PCMCIA_BUS
)
212 if (BUSTYPE(bustype
) == PCI_BUS
) {
213 if (!si_ldo_war((si_t
*)sii
, devid
))
217 /* kludge to enable the clock on the 4306 which lacks a slowclock */
218 if (BUSTYPE(bustype
) == PCI_BUS
&& !si_ispcie(sii
))
219 si_clkctl_xtal(&sii
->pub
, XTAL
|PLL
, ON
);
226 BCMATTACHFN(si_buscore_setup
)(si_info_t
*sii
, chipcregs_t
*cc
, uint bustype
, uint32 savewin
,
227 uint
*origidx
, void *regs
)
231 uint pciidx
, pcieidx
, pcirev
, pcierev
;
233 cc
= si_setcoreidx(&sii
->pub
, SI_CC_IDX
);
236 /* get chipcommon rev */
237 sii
->pub
.ccrev
= (int)si_corerev(&sii
->pub
);
239 /* get chipcommon chipstatus */
240 if (sii
->pub
.ccrev
>= 11)
241 sii
->pub
.chipst
= R_REG(sii
->osh
, &cc
->chipstatus
);
243 /* get chipcommon capabilites */
244 sii
->pub
.cccaps
= R_REG(sii
->osh
, &cc
->capabilities
);
245 /* get chipcommon extended capabilities */
247 if (sii
->pub
.ccrev
>= 35)
248 sii
->pub
.cccaps_ext
= R_REG(sii
->osh
, &cc
->capabilities_ext
);
250 /* get pmu rev and caps */
251 if (sii
->pub
.cccaps
& CC_CAP_PMU
) {
252 sii
->pub
.pmucaps
= R_REG(sii
->osh
, &cc
->pmucapabilities
);
253 sii
->pub
.pmurev
= sii
->pub
.pmucaps
& PCAP_REV_MASK
;
256 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
257 sii
->pub
.ccrev
, sii
->pub
.cccaps
, sii
->pub
.chipst
, sii
->pub
.pmurev
,
260 /* figure out bus/orignal core idx */
261 sii
->pub
.buscoretype
= NODEV_CORE_ID
;
262 sii
->pub
.buscorerev
= NOREV
;
263 sii
->pub
.buscoreidx
= BADIDX
;
266 pcirev
= pcierev
= NOREV
;
267 pciidx
= pcieidx
= BADIDX
;
269 for (i
= 0; i
< sii
->numcores
; i
++) {
272 si_setcoreidx(&sii
->pub
, i
);
273 cid
= si_coreid(&sii
->pub
);
274 crev
= si_corerev(&sii
->pub
);
276 /* Display cores found */
277 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
278 i
, cid
, crev
, sii
->coresba
[i
], sii
->regs
[i
]));
280 if (BUSTYPE(bustype
) == PCI_BUS
) {
281 if (cid
== PCI_CORE_ID
) {
285 } else if (cid
== PCIE_CORE_ID
) {
290 } else if ((BUSTYPE(bustype
) == PCMCIA_BUS
) &&
291 (cid
== PCMCIA_CORE_ID
)) {
292 sii
->pub
.buscorerev
= crev
;
293 sii
->pub
.buscoretype
= cid
;
294 sii
->pub
.buscoreidx
= i
;
297 /* find the core idx before entering this func. */
298 if ((savewin
&& (savewin
== sii
->coresba
[i
])) ||
299 (regs
== sii
->regs
[i
]))
310 sii
->pub
.buscoretype
= PCI_CORE_ID
;
311 sii
->pub
.buscorerev
= pcirev
;
312 sii
->pub
.buscoreidx
= pciidx
;
314 sii
->pub
.buscoretype
= PCIE_CORE_ID
;
315 sii
->pub
.buscorerev
= pcierev
;
316 sii
->pub
.buscoreidx
= pcieidx
;
319 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii
->pub
.buscoreidx
, sii
->pub
.buscoretype
,
320 sii
->pub
.buscorerev
));
322 if (BUSTYPE(sii
->pub
.bustype
) == SI_BUS
&& (CHIPID(sii
->pub
.chip
) == BCM4712_CHIP_ID
) &&
323 (sii
->pub
.chippkg
!= BCM4712LARGE_PKG_ID
) && (CHIPREV(sii
->pub
.chiprev
) <= 3))
324 OR_REG(sii
->osh
, &cc
->slow_clk_ctl
, SCC_SS_XTAL
);
326 /* fixup necessary chip/core configurations */
327 if (BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
) {
330 ((sii
->pch
= (void *)(uintptr
)pcicore_init(&sii
->pub
, sii
->osh
,
331 (void *)PCIEREGS(sii
))) == NULL
))
334 if (si_pci_fixcfg(&sii
->pub
)) {
335 SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
341 /* return to the original core */
342 si_setcoreidx(&sii
->pub
, *origidx
);
348 BCMATTACHFN(si_nvram_process
)(si_info_t
*sii
, char *pvars
)
351 if (BUSTYPE(sii
->pub
.bustype
) == PCMCIA_BUS
) {
352 w
= getintvar(pvars
, "regwindowsz");
353 sii
->memseg
= (w
<= CFTABLE_REGWIN_2K
) ? TRUE
: FALSE
;
356 /* get boardtype and boardrev */
357 switch (BUSTYPE(sii
->pub
.bustype
)) {
359 #if defined(BCMHOSTVARS)
360 sii
->pub
.boardvendor
= VENDOR_BROADCOM
;
361 sii
->pub
.boardtype
= getintvar(pvars
, "boardtype");
362 #else /* !BCMHOSTVARS */
363 /* do a pci config read to get subsystem id and subvendor id */
364 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_SVID
, sizeof(uint32
));
365 /* Let nvram variables override subsystem Vend/ID */
366 if ((sii
->pub
.boardvendor
= (uint16
)si_getdevpathintvar(&sii
->pub
, "boardvendor"))
368 sii
->pub
.boardvendor
= w
& 0xffff;
370 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
371 sii
->pub
.boardvendor
, w
& 0xffff));
372 if ((sii
->pub
.boardtype
= (uint16
)si_getdevpathintvar(&sii
->pub
, "boardtype"))
374 sii
->pub
.boardtype
= (w
>> 16) & 0xffff;
376 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
377 sii
->pub
.boardtype
, (w
>> 16) & 0xffff));
378 #endif /* BCMHOSTVARS */
382 sii
->pub
.boardvendor
= getintvar(pvars
, "manfid");
383 sii
->pub
.boardtype
= getintvar(pvars
, "prodid");
389 sii
->pub
.boardvendor
= VENDOR_BROADCOM
;
390 if (pvars
== NULL
|| ((sii
->pub
.boardtype
= getintvar(pvars
, "prodid")) == 0))
391 if ((sii
->pub
.boardtype
= getintvar(NULL
, "boardtype")) == 0)
392 sii
->pub
.boardtype
= 0xffff;
394 if (CHIPTYPE(sii
->pub
.socitype
) == SOCI_UBUS
) {
395 /* do a pci config read to get subsystem id and subvendor id */
396 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_SVID
, sizeof(uint32
));
397 sii
->pub
.boardvendor
= w
& 0xffff;
398 sii
->pub
.boardtype
= (w
>> 16) & 0xffff;
403 if (sii
->pub
.boardtype
== 0) {
404 SI_ERROR(("si_doattach: unknown board type\n"));
405 ASSERT(sii
->pub
.boardtype
);
408 sii
->pub
.boardrev
= getintvar(pvars
, "boardrev");
409 sii
->pub
.boardflags
= getintvar(pvars
, "boardflags");
412 #if !defined(_CFE_) || defined(CFG_WL)
414 BCMATTACHFN(si_sromvars_fixup_4331
)(si_t
*sih
, char *pvars
)
417 const char *sromvars
[] =
418 {"extpagain2g", "extpagain5g"};
419 int sromvars_size
= sizeof(sromvars
)/sizeof(char *);
421 uint boardtype
= sih
->boardtype
;
422 uint boardrev
= sih
->boardrev
;
423 bool update
= ((boardtype
== BCM94331BU_SSID
) ||
424 (boardtype
== BCM94331S9BU_SSID
) ||
425 (boardtype
== BCM94331MCI_SSID
) ||
426 (boardtype
== BCM94331MC_SSID
) ||
427 (boardtype
== BCM94331PCIEBT4_SSID
) ||
428 (boardtype
== BCM94331X19
&& boardrev
== 0x1100) ||
429 (boardtype
== BCM94331HM_SSID
&& boardrev
< 0x1152));
431 if (pvars
== NULL
|| !update
) {
435 for (ii
= 0; ii
< sromvars_size
; ii
++) {
436 char* val
= getvar(pvars
, sromvars
[ii
]);
438 while (val
&& *val
) {
444 #endif /* !_CFE_ || CFG_WL */
447 extern uint8 patch_pair
;
448 #endif /* CONFIG_XIP */
451 BCMATTACHFN(si_doattach
)(si_info_t
*sii
, uint devid
, osl_t
*osh
, void *regs
,
452 uint bustype
, void *sdh
, char **vars
, uint
*varsz
)
454 struct si_pub
*sih
= &sii
->pub
;
460 ASSERT(GOODREGS(regs
));
462 bzero((uchar
*)sii
, sizeof(si_info_t
));
466 sih
->buscoreidx
= BADIDX
;
472 #ifdef SI_ENUM_BASE_VARIABLE
473 si_enum_base_init(sih
, bustype
);
474 #endif /* SI_ENUM_BASE_VARIABLE */
476 /* check to see if we are a si core mimic'ing a pci core */
477 if ((bustype
== PCI_BUS
) &&
478 (OSL_PCI_READ_CONFIG(sii
->osh
, PCI_SPROM_CONTROL
, sizeof(uint32
)) == 0xffffffff)) {
479 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
480 "devid:0x%x\n", __FUNCTION__
, devid
));
484 /* find Chipcommon address */
485 if (bustype
== PCI_BUS
) {
486 savewin
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_BAR0_WIN
, sizeof(uint32
));
487 if (!GOODCOREADDR(savewin
, SI_ENUM_BASE
))
488 savewin
= SI_ENUM_BASE
;
489 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, 4, SI_ENUM_BASE
);
490 cc
= (chipcregs_t
*)regs
;
492 cc
= (chipcregs_t
*)REG_MAP(SI_ENUM_BASE
, SI_CORE_SIZE
);
495 sih
->bustype
= bustype
;
496 if (bustype
!= BUSTYPE(bustype
)) {
497 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
498 bustype
, BUSTYPE(bustype
)));
502 /* bus/core/clk setup for register access */
503 if (!si_buscore_prep(sii
, bustype
, devid
, sdh
)) {
504 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype
));
508 /* ChipID recognition.
509 * We assume we can read chipid at offset 0 from the regs arg.
510 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
511 * some way of recognizing them needs to be added here.
513 w
= R_REG(osh
, &cc
->chipid
);
514 sih
->socitype
= (w
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
515 /* Might as wll fill in chip id rev & pkg */
516 sih
->chip
= w
& CID_ID_MASK
;
517 sih
->chiprev
= (w
& CID_REV_MASK
) >> CID_REV_SHIFT
;
518 sih
->chippkg
= (w
& CID_PKG_MASK
) >> CID_PKG_SHIFT
;
520 if ((CHIPID(sih
->chip
) == BCM4329_CHIP_ID
) && (sih
->chiprev
== 0) &&
521 (sih
->chippkg
!= BCM4329_289PIN_PKG_ID
)) {
522 sih
->chippkg
= BCM4329_182PIN_PKG_ID
;
524 sih
->issim
= IS_SIM(sih
->chippkg
);
527 if (CHIPTYPE(sii
->pub
.socitype
) == SOCI_SB
) {
528 SI_MSG(("Found chip type SB (0x%08x)\n", w
));
529 sb_scan(&sii
->pub
, regs
, devid
);
530 } else if (CHIPTYPE(sii
->pub
.socitype
) == SOCI_AI
) {
531 SI_MSG(("Found chip type AI (0x%08x)\n", w
));
532 /* pass chipc address instead of original core base */
533 ai_scan(&sii
->pub
, (void *)(uintptr
)cc
, devid
);
534 } else if (CHIPTYPE(sii
->pub
.socitype
) == SOCI_UBUS
) {
535 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w
, sih
->chip
));
536 /* pass chipc address instead of original core base */
537 ub_scan(&sii
->pub
, (void *)(uintptr
)cc
, devid
);
539 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w
));
542 /* no cores found, bail out */
543 if (sii
->numcores
== 0) {
544 SI_ERROR(("si_doattach: could not find any cores\n"));
547 /* bus/core/clk setup */
549 if (!si_buscore_setup(sii
, cc
, bustype
, savewin
, &origidx
, regs
)) {
550 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
554 #if !defined(_CFE_) || defined(CFG_WL)
555 if (CHIPID(sih
->chip
) == BCM4322_CHIP_ID
&& (((sih
->chipst
& CST4322_SPROM_OTP_SEL_MASK
)
556 >> CST4322_SPROM_OTP_SEL_SHIFT
) == (CST4322_OTP_PRESENT
|
557 CST4322_SPROM_PRESENT
))) {
558 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__
));
562 /* assume current core is CC */
563 if ((sii
->pub
.ccrev
== 0x25) && ((CHIPID(sih
->chip
) == BCM43236_CHIP_ID
||
564 CHIPID(sih
->chip
) == BCM43235_CHIP_ID
||
565 CHIPID(sih
->chip
) == BCM43234_CHIP_ID
||
566 CHIPID(sih
->chip
) == BCM43238_CHIP_ID
) &&
567 (CHIPREV(sii
->pub
.chiprev
) <= 2))) {
569 if ((cc
->chipstatus
& CST43236_BP_CLK
) != 0) {
571 clkdiv
= R_REG(osh
, &cc
->clkdiv
);
572 /* otp_clk_div is even number, 120/14 < 9mhz */
573 clkdiv
= (clkdiv
& ~CLKD_OTP
) | (14 << CLKD_OTP_SHIFT
);
574 W_REG(osh
, &cc
->clkdiv
, clkdiv
);
575 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__
, clkdiv
));
580 if (bustype
== PCI_BUS
) {
581 if ((CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) ||
582 (CHIPID(sih
->chip
) == BCM43431_CHIP_ID
)) {
583 /* set default mux pin to SROM */
584 si_chipcontrl_epa4331(sih
, FALSE
);
585 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, watchdog
), ~0, 100);
586 OSL_DELAY(20000); /* Srom read takes ~12mS */
589 /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
590 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
591 * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words.
596 if ((CHIPID(sih
->chip
) == BCM4314_CHIP_ID
) ||
597 (CHIPID(sih
->chip
) == BCM43142_CHIP_ID
)) {
599 } else if ((CHIPID(sih
->chip
) == BCM43227_CHIP_ID
) ||
600 (CHIPID(sih
->chip
) == BCM43131_CHIP_ID
) ||
601 (CHIPID(sih
->chip
) == BCM43228_CHIP_ID
)) {
605 if (otpclkdiv
!= 0) {
606 uint clkdiv
, savecore
;
607 savecore
= si_coreidx(sih
);
608 si_setcore(sih
, CC_CORE_ID
, 0);
610 clkdiv
= R_REG(osh
, &cc
->clkdiv
);
611 clkdiv
= (clkdiv
& ~CLKD_OTP
) | (otpclkdiv
<< CLKD_OTP_SHIFT
);
612 W_REG(osh
, &cc
->clkdiv
, clkdiv
);
614 SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__
, clkdiv
));
615 si_setcoreidx(sih
, savecore
);
620 #endif /* !_CFE_ || CFG_WL */
621 #ifdef SI_SPROM_PROBE
623 #endif /* SI_SPROM_PROBE */
625 #if !defined(BCMHIGHSDIO)
626 /* Init nvram from flash if it exists */
627 nvram_init((void *)&(sii
->pub
));
629 /* Init nvram from sprom/otp if they exist */
630 if (srom_var_init(&sii
->pub
, BUSTYPE(bustype
), regs
, sii
->osh
, vars
, varsz
)) {
631 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
634 pvars
= vars
? *vars
: NULL
;
635 si_nvram_process(sii
, pvars
);
637 #if !defined(_CFE_) || defined(CFG_WL)
638 if (bustype
== PCI_BUS
) {
639 if ((CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) ||
640 (CHIPID(sih
->chip
) == BCM43431_CHIP_ID
)) {
641 si_sromvars_fixup_4331(sih
, pvars
);
644 #endif /* _!CFE_ || CFG_WL */
646 /* === NVRAM, clock is ready === */
653 /* patch the ROM if there are any patch pairs from OTP/SPROM */
656 hnd_tcam_bootloader_load(si_setcore(sih
, SOCRAM_CORE_ID
, 0), pvars
);
658 si_setcoreidx(sih
, origidx
);
660 #endif /* CONFIG_XIP */
662 if (sii
->pub
.ccrev
>= 20) {
663 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
664 W_REG(osh
, &cc
->gpiopullup
, 0);
665 W_REG(osh
, &cc
->gpiopulldown
, 0);
666 si_setcoreidx(sih
, origidx
);
669 /* PMU specific initializations */
670 if (PMUCTL_ENAB(sih
)) {
672 si_pmu_init(sih
, sii
->osh
);
673 si_pmu_chip_init(sih
, sii
->osh
);
674 xtalfreq
= getintvar(pvars
, "xtalfreq");
675 /* If xtalfreq var not available, try to measure it */
677 xtalfreq
= si_pmu_measure_alpclk(sih
, sii
->osh
);
678 si_pmu_pll_init(sih
, sii
->osh
, xtalfreq
);
679 si_pmu_res_init(sih
, sii
->osh
);
680 si_pmu_swreg_init(sih
, sii
->osh
);
683 /* setup the GPIO based LED powersave register */
684 if (sii
->pub
.ccrev
>= 16) {
685 if ((w
= getintvar(pvars
, "leddc")) == 0)
686 w
= DEFAULT_GPIOTIMERVAL
;
687 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, gpiotimerval
), ~0, w
);
690 if (PCI_FORCEHT(sii
)) {
691 SI_MSG(("si_doattach: force HT\n"));
692 sih
->pci_pr32414
= TRUE
;
694 _si_clkctl_cc(sii
, CLK_FAST
);
697 #if !defined(_CFE_) || defined(CFG_WL)
699 ASSERT(sii
->pch
!= NULL
);
701 pcicore_attach(sii
->pch
, pvars
, SI_DOATTACH
);
703 if (((CHIPID(sih
->chip
) == BCM4311_CHIP_ID
) && (CHIPREV(sih
->chiprev
) == 2)) ||
704 (CHIPID(sih
->chip
) == BCM4312_CHIP_ID
)) {
705 SI_MSG(("si_doattach: clear initiator timeout\n"));
706 sb_set_initiator_to(sih
, 0x3, si_findcoreidx(sih
, D11_CORE_ID
, 0));
710 if ((CHIPID(sih
->chip
) == BCM43224_CHIP_ID
) ||
711 (CHIPID(sih
->chip
) == BCM43421_CHIP_ID
)) {
712 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
713 if (CHIPREV(sih
->chiprev
) == 0) {
714 SI_MSG(("Applying 43224A0 WARs\n"));
715 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol
),
716 CCTRL43224_GPIO_TOGGLE
, CCTRL43224_GPIO_TOGGLE
);
717 si_pmu_chipcontrol(sih
, 0, CCTRL_43224A0_12MA_LED_DRIVE
,
718 CCTRL_43224A0_12MA_LED_DRIVE
);
720 if (CHIPREV(sih
->chiprev
) >= 1) {
721 SI_MSG(("Applying 43224B0+ WARs\n"));
722 si_pmu_chipcontrol(sih
, 0, CCTRL_43224B0_12MA_LED_DRIVE
,
723 CCTRL_43224B0_12MA_LED_DRIVE
);
727 if (CHIPID(sih
->chip
) == BCM4313_CHIP_ID
) {
728 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
729 SI_MSG(("Applying 4313 WARs\n"));
730 si_pmu_chipcontrol(sih
, 0, CCTRL_4313_12MA_LED_DRIVE
, CCTRL_4313_12MA_LED_DRIVE
);
732 #endif /* !_CFE_ || CFG_WL */
735 /* clear any previous epidiag-induced target abort */
736 si_taclear(sih
, FALSE
);
742 if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
744 pcicore_deinit(sii
->pch
);
751 /* may be called with core in reset */
753 BCMATTACHFN(si_detach
)(si_t
*sih
)
759 struct si_pub
*si_local
= NULL
;
760 bcopy(&sih
, &si_local
, sizeof(si_t
*));
768 if (BUSTYPE(sih
->bustype
) == SI_BUS
)
769 for (idx
= 0; idx
< SI_MAXCORES
; idx
++)
770 if (sii
->regs
[idx
]) {
771 REG_UNMAP(sii
->regs
[idx
]);
772 sii
->regs
[idx
] = NULL
;
776 nvram_exit((void *)si_local
); /* free up nvram buffers */
779 if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
781 pcicore_deinit(sii
->pch
);
785 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
787 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
788 MFREE(sii
->osh
, sii
, sizeof(si_info_t
));
801 si_setosh(si_t
*sih
, osl_t
*osh
)
806 if (sii
->osh
!= NULL
) {
807 SI_ERROR(("osh is already set....\n"));
813 /* register driver interrupt disabling and restoring callback functions */
815 si_register_intr_callback(si_t
*sih
, void *intrsoff_fn
, void *intrsrestore_fn
,
816 void *intrsenabled_fn
, void *intr_arg
)
821 sii
->intr_arg
= intr_arg
;
822 sii
->intrsoff_fn
= (si_intrsoff_t
)intrsoff_fn
;
823 sii
->intrsrestore_fn
= (si_intrsrestore_t
)intrsrestore_fn
;
824 sii
->intrsenabled_fn
= (si_intrsenabled_t
)intrsenabled_fn
;
825 /* save current core id. when this function called, the current core
826 * must be the core which provides driver functions(il, et, wl, etc.)
828 sii
->dev_coreid
= sii
->coreid
[sii
->curidx
];
832 si_deregister_intr_callback(si_t
*sih
)
837 sii
->intrsoff_fn
= NULL
;
841 si_intflag(si_t
*sih
)
843 si_info_t
*sii
= SI_INFO(sih
);
845 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
846 return sb_intflag(sih
);
847 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
848 return R_REG(sii
->osh
, ((uint32
*)(uintptr
)
849 (sii
->oob_router
+ OOB_STATUSA
)));
859 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
861 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
863 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
872 si_setint(si_t
*sih
, int siflag
)
874 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
875 sb_setint(sih
, siflag
);
876 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
877 ai_setint(sih
, siflag
);
878 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
879 ub_setint(sih
, siflag
);
890 return sii
->coreid
[sii
->curidx
];
894 si_coreidx(si_t
*sih
)
902 /* return the core-type instantiation # of the current core */
904 si_coreunit(si_t
*sih
)
917 ASSERT(GOODREGS(sii
->curmap
));
918 coreid
= si_coreid(sih
);
920 /* count the cores of our type */
921 for (i
= 0; i
< idx
; i
++)
922 if (sii
->coreid
[i
] == coreid
)
929 si_corevendor(si_t
*sih
)
931 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
932 return sb_corevendor(sih
);
933 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
934 return ai_corevendor(sih
);
935 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
936 return ub_corevendor(sih
);
944 si_backplane64(si_t
*sih
)
946 return ((sih
->cccaps
& CC_CAP_BKPLN64
) != 0);
950 si_corerev(si_t
*sih
)
952 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
953 return sb_corerev(sih
);
954 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
955 return ai_corerev(sih
);
956 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
957 return ub_corerev(sih
);
964 /* return index of coreid or BADIDX if not found */
966 si_findcoreidx(si_t
*sih
, uint coreid
, uint coreunit
)
976 for (i
= 0; i
< sii
->numcores
; i
++)
977 if (sii
->coreid
[i
] == coreid
) {
978 if (found
== coreunit
)
986 /* return list of found cores */
988 si_corelist(si_t
*sih
, uint coreid
[])
994 bcopy((uchar
*)sii
->coreid
, (uchar
*)coreid
, (sii
->numcores
* sizeof(uint
)));
995 return (sii
->numcores
);
998 /* return current register mapping */
1000 si_coreregs(si_t
*sih
)
1005 ASSERT(GOODREGS(sii
->curmap
));
1007 return (sii
->curmap
);
1011 * This function changes logical "focus" to the indicated core;
1012 * must be called with interrupts off.
1013 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1016 si_setcore(si_t
*sih
, uint coreid
, uint coreunit
)
1020 idx
= si_findcoreidx(sih
, coreid
, coreunit
);
1024 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1025 return sb_setcoreidx(sih
, idx
);
1026 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1027 return ai_setcoreidx(sih
, idx
);
1028 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1029 return ub_setcoreidx(sih
, idx
);
1037 si_setcoreidx(si_t
*sih
, uint coreidx
)
1039 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1040 return sb_setcoreidx(sih
, coreidx
);
1041 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1042 return ai_setcoreidx(sih
, coreidx
);
1043 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1044 return ub_setcoreidx(sih
, coreidx
);
1051 /* Turn off interrupt as required by sb_setcore, before switch core */
1053 si_switch_core(si_t
*sih
, uint coreid
, uint
*origidx
, uint
*intr_val
)
1061 /* Overloading the origidx variable to remember the coreid,
1062 * this works because the core ids cannot be confused with
1066 if (coreid
== CC_CORE_ID
)
1067 return (void *)CCREGS_FAST(sii
);
1068 else if (coreid
== sih
->buscoretype
)
1069 return (void *)PCIEREGS(sii
);
1071 INTR_OFF(sii
, *intr_val
);
1072 *origidx
= sii
->curidx
;
1073 cc
= si_setcore(sih
, coreid
, 0);
1079 /* restore coreidx and restore interrupt */
1081 si_restore_core(si_t
*sih
, uint coreid
, uint intr_val
)
1086 if (SI_FAST(sii
) && ((coreid
== CC_CORE_ID
) || (coreid
== sih
->buscoretype
)))
1089 si_setcoreidx(sih
, coreid
);
1090 INTR_RESTORE(sii
, intr_val
);
1094 si_numaddrspaces(si_t
*sih
)
1096 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1097 return sb_numaddrspaces(sih
);
1098 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1099 return ai_numaddrspaces(sih
);
1100 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1101 return ub_numaddrspaces(sih
);
1109 si_addrspace(si_t
*sih
, uint asidx
)
1111 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1112 return sb_addrspace(sih
, asidx
);
1113 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1114 return ai_addrspace(sih
, asidx
);
1115 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1116 return ub_addrspace(sih
, asidx
);
1124 si_addrspacesize(si_t
*sih
, uint asidx
)
1126 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1127 return sb_addrspacesize(sih
, asidx
);
1128 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1129 return ai_addrspacesize(sih
, asidx
);
1130 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1131 return ub_addrspacesize(sih
, asidx
);
1139 si_coreaddrspaceX(si_t
*sih
, uint asidx
, uint32
*addr
, uint32
*size
)
1141 /* Only supported for SOCI_AI */
1142 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1143 ai_coreaddrspaceX(sih
, asidx
, addr
, size
);
1149 si_core_cflags(si_t
*sih
, uint32 mask
, uint32 val
)
1151 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1152 return sb_core_cflags(sih
, mask
, val
);
1153 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1154 return ai_core_cflags(sih
, mask
, val
);
1155 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1156 return ub_core_cflags(sih
, mask
, val
);
1164 si_core_cflags_wo(si_t
*sih
, uint32 mask
, uint32 val
)
1166 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1167 sb_core_cflags_wo(sih
, mask
, val
);
1168 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1169 ai_core_cflags_wo(sih
, mask
, val
);
1170 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1171 ub_core_cflags_wo(sih
, mask
, val
);
1177 si_core_sflags(si_t
*sih
, uint32 mask
, uint32 val
)
1179 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1180 return sb_core_sflags(sih
, mask
, val
);
1181 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1182 return ai_core_sflags(sih
, mask
, val
);
1183 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1184 return ub_core_sflags(sih
, mask
, val
);
1192 si_iscoreup(si_t
*sih
)
1194 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1195 return sb_iscoreup(sih
);
1196 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1197 return ai_iscoreup(sih
);
1198 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1199 return ub_iscoreup(sih
);
1207 si_write_wrapperreg(si_t
*sih
, uint32 offset
, uint32 val
)
1209 /* only for 4319, no requirement for SOCI_SB */
1210 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
) {
1211 ai_write_wrap_reg(sih
, offset
, val
);
1220 si_corereg(si_t
*sih
, uint coreidx
, uint regoff
, uint mask
, uint val
)
1222 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1223 return sb_corereg(sih
, coreidx
, regoff
, mask
, val
);
1224 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1225 return ai_corereg(sih
, coreidx
, regoff
, mask
, val
);
1226 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1227 return ub_corereg(sih
, coreidx
, regoff
, mask
, val
);
1235 si_core_disable(si_t
*sih
, uint32 bits
)
1237 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1238 sb_core_disable(sih
, bits
);
1239 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1240 ai_core_disable(sih
, bits
);
1241 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1242 ub_core_disable(sih
, bits
);
1246 si_core_reset(si_t
*sih
, uint32 bits
, uint32 resetbits
)
1248 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1249 sb_core_reset(sih
, bits
, resetbits
);
1250 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1251 ai_core_reset(sih
, bits
, resetbits
);
1252 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1253 ub_core_reset(sih
, bits
, resetbits
);
1256 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1258 si_corebist(si_t
*sih
)
1263 /* Read core control flags */
1264 cflags
= si_core_cflags(sih
, 0, 0);
1266 /* Set bist & fgc */
1267 si_core_cflags(sih
, ~0, (SICF_BIST_EN
| SICF_FGC
));
1269 /* Wait for bist done */
1270 SPINWAIT(((si_core_sflags(sih
, 0, 0) & SISF_BIST_DONE
) == 0), 100000);
1272 if (si_core_sflags(sih
, 0, 0) & SISF_BIST_ERROR
)
1273 result
= BCME_ERROR
;
1275 /* Reset core control flags */
1276 si_core_cflags(sih
, 0xffff, cflags
);
1282 BCMINITFN(factor6
)(uint32 x
)
1285 case CC_F6_2
: return 2;
1286 case CC_F6_3
: return 3;
1287 case CC_F6_4
: return 4;
1288 case CC_F6_5
: return 5;
1289 case CC_F6_6
: return 6;
1290 case CC_F6_7
: return 7;
1295 /* calculate the speed the SI would run at given a set of clockcontrol values */
1297 BCMINITFN(si_clock_rate
)(uint32 pll_type
, uint32 n
, uint32 m
)
1299 uint32 n1
, n2
, clock
, m1
, m2
, m3
, mc
;
1301 n1
= n
& CN_N1_MASK
;
1302 n2
= (n
& CN_N2_MASK
) >> CN_N2_SHIFT
;
1304 if (pll_type
== PLL_TYPE6
) {
1305 if (m
& CC_T6_MMASK
)
1309 } else if ((pll_type
== PLL_TYPE1
) ||
1310 (pll_type
== PLL_TYPE3
) ||
1311 (pll_type
== PLL_TYPE4
) ||
1312 (pll_type
== PLL_TYPE7
)) {
1315 } else if (pll_type
== PLL_TYPE2
) {
1318 ASSERT((n1
>= 2) && (n1
<= 7));
1319 ASSERT((n2
>= 5) && (n2
<= 23));
1320 } else if (pll_type
== PLL_TYPE5
) {
1324 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1325 if ((pll_type
== PLL_TYPE3
) ||
1326 (pll_type
== PLL_TYPE7
)) {
1327 clock
= CC_CLOCK_BASE2
* n1
* n2
;
1329 clock
= CC_CLOCK_BASE1
* n1
* n2
;
1334 m1
= m
& CC_M1_MASK
;
1335 m2
= (m
& CC_M2_MASK
) >> CC_M2_SHIFT
;
1336 m3
= (m
& CC_M3_MASK
) >> CC_M3_SHIFT
;
1337 mc
= (m
& CC_MC_MASK
) >> CC_MC_SHIFT
;
1339 if ((pll_type
== PLL_TYPE1
) ||
1340 (pll_type
== PLL_TYPE3
) ||
1341 (pll_type
== PLL_TYPE4
) ||
1342 (pll_type
== PLL_TYPE7
)) {
1344 if ((pll_type
== PLL_TYPE1
) || (pll_type
== PLL_TYPE3
))
1351 case CC_MC_BYPASS
: return (clock
);
1352 case CC_MC_M1
: return (clock
/ m1
);
1353 case CC_MC_M1M2
: return (clock
/ (m1
* m2
));
1354 case CC_MC_M1M2M3
: return (clock
/ (m1
* m2
* m3
));
1355 case CC_MC_M1M3
: return (clock
/ (m1
* m3
));
1356 default: return (0);
1359 ASSERT(pll_type
== PLL_TYPE2
);
1364 ASSERT((m1
>= 2) && (m1
<= 7));
1365 ASSERT((m2
>= 3) && (m2
<= 10));
1366 ASSERT((m3
>= 2) && (m3
<= 7));
1368 if ((mc
& CC_T2MC_M1BYP
) == 0)
1370 if ((mc
& CC_T2MC_M2BYP
) == 0)
1372 if ((mc
& CC_T2MC_M3BYP
) == 0)
1380 BCMINITFN(si_clock
)(si_t
*sih
)
1386 uint32 pll_type
, rate
;
1390 INTR_OFF(sii
, intr_val
);
1391 if (PMUCTL_ENAB(sih
)) {
1392 rate
= si_pmu_si_clock(sih
, sii
->osh
);
1397 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
1400 n
= R_REG(sii
->osh
, &cc
->clockcontrol_n
);
1401 pll_type
= sih
->cccaps
& CC_CAP_PLL_MASK
;
1402 if (pll_type
== PLL_TYPE6
)
1403 m
= R_REG(sii
->osh
, &cc
->clockcontrol_m3
);
1404 else if (pll_type
== PLL_TYPE3
)
1405 m
= R_REG(sii
->osh
, &cc
->clockcontrol_m2
);
1407 m
= R_REG(sii
->osh
, &cc
->clockcontrol_sb
);
1409 /* calculate rate */
1410 rate
= si_clock_rate(pll_type
, n
, m
);
1412 if (pll_type
== PLL_TYPE3
)
1415 /* switch back to previous core */
1416 si_setcoreidx(sih
, idx
);
1418 INTR_RESTORE(sii
, intr_val
);
1424 BCMINITFN(si_alp_clock
)(si_t
*sih
)
1426 if (PMUCTL_ENAB(sih
))
1427 return si_pmu_alp_clock(sih
, si_osh(sih
));
1433 BCMINITFN(si_ilp_clock
)(si_t
*sih
)
1435 if (PMUCTL_ENAB(sih
))
1436 return si_pmu_ilp_clock(sih
, si_osh(sih
));
1441 /* set chip watchdog reset timer to fire in 'ticks' */
1443 si_watchdog(si_t
*sih
, uint ticks
)
1447 if (PMUCTL_ENAB(sih
)) {
1449 #if !defined(_CFE_) || defined(CFG_WL)
1450 if ((CHIPID(sih
->chip
) == BCM4319_CHIP_ID
) &&
1451 (CHIPREV(sih
->chiprev
) == 0) && (ticks
!= 0)) {
1452 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, clk_ctl_st
), ~0, 0x2);
1453 si_setcore(sih
, USB20D_CORE_ID
, 0);
1454 si_core_disable(sih
, 1);
1455 si_setcore(sih
, CC_CORE_ID
, 0);
1457 #endif /* !_CFE_ || CFG_WL */
1459 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
)
1462 nb
= (sih
->ccrev
< 26) ? 16 : ((sih
->ccrev
>= 37) ? 32 : 24);
1463 /* The mips compiler uses the sllv instruction,
1464 * so we specially handle the 32-bit case.
1469 maxt
= ((1 << nb
) - 1);
1473 else if (ticks
> maxt
)
1476 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, pmuwatchdog
), ~0, ticks
);
1478 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1479 si_clkctl_cc(sih
, ticks
? CLK_FAST
: CLK_DYNAMIC
);
1480 maxt
= (1 << 28) - 1;
1484 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, watchdog
), ~0, ticks
);
1488 /* trigger watchdog reset after ms milliseconds */
1490 si_watchdog_ms(si_t
*sih
, uint32 ms
)
1492 si_watchdog(sih
, wd_msticks
* ms
);
1495 #if defined(BCMDBG_ERR) || defined(BCMASSERT_SUPPORT) || defined(BCMDBG_DUMP)
1497 si_taclear(si_t
*sih
, bool details
)
1499 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1500 return sb_taclear(sih
, details
);
1501 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1503 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1513 BCMATTACHFN(si_d11_devid
)(si_t
*sih
)
1515 si_info_t
*sii
= SI_INFO(sih
);
1518 /* Fix device id for dual band BCM4328 */
1519 if (CHIPID(sih
->chip
) == BCM4328_CHIP_ID
&&
1520 (sih
->chippkg
== BCM4328USBDUAL_PKG_ID
|| sih
->chippkg
== BCM4328SDIODUAL_PKG_ID
))
1521 device
= BCM4328_D11DUAL_ID
;
1523 /* normal case: nvram variable with devpath->devid->wl0id */
1524 if ((device
= (uint16
)si_getdevpathintvar(sih
, "devid")) != 0)
1526 /* Get devid from OTP/SPROM depending on where the SROM is read */
1527 else if ((device
= (uint16
)getintvar(sii
->vars
, "devid")) != 0)
1529 /* no longer support wl0id, but keep the code here for backward compatibility. */
1530 else if ((device
= (uint16
)getintvar(sii
->vars
, "wl0id")) != 0)
1532 else if (CHIPID(sih
->chip
) == BCM4712_CHIP_ID
) {
1533 /* Chip specific conversion */
1534 if (sih
->chippkg
== BCM4712SMALL_PKG_ID
)
1535 device
= BCM4306_D11G_ID
;
1537 device
= BCM4306_D11DUAL_ID
;
1547 BCMATTACHFN(si_corepciid
)(si_t
*sih
, uint func
, uint16
*pcivendor
, uint16
*pcidevice
,
1548 uint8
*pciclass
, uint8
*pcisubclass
, uint8
*pciprogif
,
1551 uint16 vendor
= 0xffff, device
= 0xffff;
1552 uint8
class, subclass
, progif
= 0;
1553 uint8 header
= PCI_HEADER_NORMAL
;
1554 uint32 core
= si_coreid(sih
);
1556 /* Verify whether the function exists for the core */
1557 if (func
>= (uint
)(core
== USB20H_CORE_ID
? 2 : 1))
1560 /* Known vendor translations */
1561 switch (si_corevendor(sih
)) {
1564 vendor
= VENDOR_BROADCOM
;
1570 /* Determine class based on known core codes */
1573 class = PCI_CLASS_NET
;
1574 subclass
= PCI_NET_ETHER
;
1575 device
= BCM47XX_ENET_ID
;
1577 case GIGETH_CORE_ID
:
1578 class = PCI_CLASS_NET
;
1579 subclass
= PCI_NET_ETHER
;
1580 device
= BCM47XX_GIGETH_ID
;
1583 class = PCI_CLASS_NET
;
1584 subclass
= PCI_NET_ETHER
;
1585 device
= BCM47XX_GMAC_ID
;
1590 case SOCRAM_CORE_ID
:
1591 class = PCI_CLASS_MEMORY
;
1592 subclass
= PCI_MEMORY_RAM
;
1593 device
= (uint16
)core
;
1597 class = PCI_CLASS_BRIDGE
;
1598 subclass
= PCI_BRIDGE_PCI
;
1599 device
= (uint16
)core
;
1600 header
= PCI_HEADER_BRIDGE
;
1602 case MIPS33_CORE_ID
:
1603 case MIPS74K_CORE_ID
:
1604 class = PCI_CLASS_CPU
;
1605 subclass
= PCI_CPU_MIPS
;
1606 device
= (uint16
)core
;
1609 class = PCI_CLASS_COMM
;
1610 subclass
= PCI_COMM_MODEM
;
1611 device
= BCM47XX_V90_ID
;
1614 class = PCI_CLASS_MMEDIA
;
1615 subclass
= PCI_MMEDIA_AUDIO
;
1616 device
= BCM47XX_AUDIO_ID
;
1619 case USB11H_CORE_ID
:
1620 class = PCI_CLASS_SERIAL
;
1621 subclass
= PCI_SERIAL_USB
;
1622 progif
= 0x10; /* OHCI */
1623 device
= BCM47XX_USBH_ID
;
1625 case USB20H_CORE_ID
:
1626 class = PCI_CLASS_SERIAL
;
1627 subclass
= PCI_SERIAL_USB
;
1628 progif
= func
== 0 ? 0x10 : 0x20; /* OHCI/EHCI */
1629 device
= BCM47XX_USB20H_ID
;
1630 header
= 0x80; /* multifunction */
1633 class = PCI_CLASS_CRYPT
;
1634 subclass
= PCI_CRYPT_NETWORK
;
1635 device
= BCM47XX_IPSEC_ID
;
1638 /* Don't use class NETWORK, so wl/et won't attempt to recognize it */
1639 class = PCI_CLASS_COMM
;
1640 subclass
= PCI_COMM_OTHER
;
1641 device
= BCM47XX_ROBO_ID
;
1644 class = PCI_CLASS_MEMORY
;
1645 subclass
= PCI_MEMORY_FLASH
;
1646 device
= (uint16
)core
;
1648 case SATAXOR_CORE_ID
:
1649 class = PCI_CLASS_XOR
;
1650 subclass
= PCI_XOR_QDMA
;
1651 device
= BCM47XX_SATAXOR_ID
;
1653 case ATA100_CORE_ID
:
1654 class = PCI_CLASS_DASDI
;
1655 subclass
= PCI_DASDI_IDE
;
1656 device
= BCM47XX_ATA100_ID
;
1658 case USB11D_CORE_ID
:
1659 class = PCI_CLASS_SERIAL
;
1660 subclass
= PCI_SERIAL_USB
;
1661 device
= BCM47XX_USBD_ID
;
1663 case USB20D_CORE_ID
:
1664 class = PCI_CLASS_SERIAL
;
1665 subclass
= PCI_SERIAL_USB
;
1666 device
= BCM47XX_USB20D_ID
;
1669 class = PCI_CLASS_NET
;
1670 subclass
= PCI_NET_OTHER
;
1671 device
= si_d11_devid(sih
);
1675 class = subclass
= progif
= 0xff;
1676 device
= (uint16
)core
;
1680 *pcivendor
= vendor
;
1681 *pcidevice
= device
;
1683 *pcisubclass
= subclass
;
1684 *pciprogif
= progif
;
1685 *pciheader
= header
;
1690 #if defined(BCMDBG) || defined(BCMDBG_DUMP)
1691 /* print interesting sbconfig registers */
1693 si_dumpregs(si_t
*sih
, struct bcmstrbuf
*b
)
1696 uint origidx
, intr_val
= 0;
1699 origidx
= sii
->curidx
;
1701 INTR_OFF(sii
, intr_val
);
1702 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1703 sb_dumpregs(sih
, b
);
1704 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1705 ai_dumpregs(sih
, b
);
1706 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1707 ub_dumpregs(sih
, b
);
1711 si_setcoreidx(sih
, origidx
);
1712 INTR_RESTORE(sii
, intr_val
);
1714 #endif /* BCMDBG || BCMDBG_DUMP */
1718 si_view(si_t
*sih
, bool verbose
)
1720 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
1721 sb_view(sih
, verbose
);
1722 else if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1723 ai_view(sih
, verbose
);
1724 else if (CHIPTYPE(sih
->socitype
) == SOCI_UBUS
)
1725 ub_view(sih
, verbose
);
1731 si_viewall(si_t
*sih
, bool verbose
)
1738 curidx
= sii
->curidx
;
1740 INTR_OFF(sii
, intr_val
);
1741 SI_ERROR(("si_viewall: num_cores %d\n", sii
->numcores
));
1742 for (i
= 0; i
< sii
->numcores
; i
++) {
1743 si_setcoreidx(sih
, i
);
1744 si_view(sih
, verbose
);
1747 si_setcoreidx(sih
, curidx
);
1748 INTR_RESTORE(sii
, intr_val
);
1752 /* return the slow clock source - LPO, XTAL, or PCI */
1754 si_slowclk_src(si_info_t
*sii
)
1758 ASSERT(SI_FAST(sii
) || si_coreid(&sii
->pub
) == CC_CORE_ID
);
1760 if (sii
->pub
.ccrev
< 6) {
1761 if ((BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
) &&
1762 (OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
)) &
1764 return (SCC_SS_PCI
);
1766 return (SCC_SS_XTAL
);
1767 } else if (sii
->pub
.ccrev
< 10) {
1768 cc
= (chipcregs_t
*)si_setcoreidx(&sii
->pub
, sii
->curidx
);
1769 return (R_REG(sii
->osh
, &cc
->slow_clk_ctl
) & SCC_SS_MASK
);
1770 } else /* Insta-clock */
1771 return (SCC_SS_XTAL
);
1774 /* return the ILP (slowclock) min or max frequency */
1776 si_slowclk_freq(si_info_t
*sii
, bool max_freq
, chipcregs_t
*cc
)
1781 ASSERT(SI_FAST(sii
) || si_coreid(&sii
->pub
) == CC_CORE_ID
);
1783 /* shouldn't be here unless we've established the chip has dynamic clk control */
1784 ASSERT(R_REG(sii
->osh
, &cc
->capabilities
) & CC_CAP_PWR_CTL
);
1786 slowclk
= si_slowclk_src(sii
);
1787 if (sii
->pub
.ccrev
< 6) {
1788 if (slowclk
== SCC_SS_PCI
)
1789 return (max_freq
? (PCIMAXFREQ
/ 64) : (PCIMINFREQ
/ 64));
1791 return (max_freq
? (XTALMAXFREQ
/ 32) : (XTALMINFREQ
/ 32));
1792 } else if (sii
->pub
.ccrev
< 10) {
1794 (((R_REG(sii
->osh
, &cc
->slow_clk_ctl
) & SCC_CD_MASK
) >> SCC_CD_SHIFT
) + 1);
1795 if (slowclk
== SCC_SS_LPO
)
1796 return (max_freq
? LPOMAXFREQ
: LPOMINFREQ
);
1797 else if (slowclk
== SCC_SS_XTAL
)
1798 return (max_freq
? (XTALMAXFREQ
/ div
) : (XTALMINFREQ
/ div
));
1799 else if (slowclk
== SCC_SS_PCI
)
1800 return (max_freq
? (PCIMAXFREQ
/ div
) : (PCIMINFREQ
/ div
));
1804 /* Chipc rev 10 is InstaClock */
1805 div
= R_REG(sii
->osh
, &cc
->system_clk_ctl
) >> SYCC_CD_SHIFT
;
1806 div
= 4 * (div
+ 1);
1807 return (max_freq
? XTALMAXFREQ
: (XTALMINFREQ
/ div
));
1813 BCMINITFN(si_clkctl_setdelay
)(si_info_t
*sii
, void *chipcregs
)
1815 chipcregs_t
*cc
= (chipcregs_t
*)chipcregs
;
1816 uint slowmaxfreq
, pll_delay
, slowclk
;
1817 uint pll_on_delay
, fref_sel_delay
;
1819 pll_delay
= PLL_DELAY
;
1821 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1822 * since the xtal will also be powered down by dynamic clk control logic.
1825 slowclk
= si_slowclk_src(sii
);
1826 if (slowclk
!= SCC_SS_XTAL
)
1827 pll_delay
+= XTAL_ON_DELAY
;
1829 /* Starting with 4318 it is ILP that is used for the delays */
1830 slowmaxfreq
= si_slowclk_freq(sii
, (sii
->pub
.ccrev
>= 10) ? FALSE
: TRUE
, cc
);
1832 pll_on_delay
= ((slowmaxfreq
* pll_delay
) + 999999) / 1000000;
1833 fref_sel_delay
= ((slowmaxfreq
* FREF_DELAY
) + 999999) / 1000000;
1835 W_REG(sii
->osh
, &cc
->pll_on_delay
, pll_on_delay
);
1836 W_REG(sii
->osh
, &cc
->fref_sel_delay
, fref_sel_delay
);
1839 /* initialize power control delay registers */
1841 BCMINITFN(si_clkctl_init
)(si_t
*sih
)
1848 if (!CCCTL_ENAB(sih
))
1852 fast
= SI_FAST(sii
);
1854 origidx
= sii
->curidx
;
1855 if ((cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
1857 } else if ((cc
= (chipcregs_t
*)CCREGS_FAST(sii
)) == NULL
)
1861 /* set all Instaclk chip ILP to 1 MHz */
1862 if (sih
->ccrev
>= 10)
1863 SET_REG(sii
->osh
, &cc
->system_clk_ctl
, SYCC_CD_MASK
,
1864 (ILP_DIV_1MHZ
<< SYCC_CD_SHIFT
));
1866 si_clkctl_setdelay(sii
, (void *)(uintptr
)cc
);
1869 si_setcoreidx(sih
, origidx
);
1872 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1874 BCMINITFN(si_clkctl_fast_pwrup_delay
)(si_t
*sih
)
1885 if (PMUCTL_ENAB(sih
)) {
1886 INTR_OFF(sii
, intr_val
);
1887 fpdelay
= si_pmu_fast_pwrup_delay(sih
, sii
->osh
);
1888 INTR_RESTORE(sii
, intr_val
);
1892 if (!CCCTL_ENAB(sih
))
1895 fast
= SI_FAST(sii
);
1898 origidx
= sii
->curidx
;
1899 INTR_OFF(sii
, intr_val
);
1900 if ((cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
1903 else if ((cc
= (chipcregs_t
*)CCREGS_FAST(sii
)) == NULL
)
1907 slowminfreq
= si_slowclk_freq(sii
, FALSE
, cc
);
1908 fpdelay
= (((R_REG(sii
->osh
, &cc
->pll_on_delay
) + 2) * 1000000) +
1909 (slowminfreq
- 1)) / slowminfreq
;
1913 si_setcoreidx(sih
, origidx
);
1914 INTR_RESTORE(sii
, intr_val
);
1919 /* turn primary xtal and/or pll off/on */
1921 si_clkctl_xtal(si_t
*sih
, uint what
, bool on
)
1924 uint32 in
, out
, outen
;
1928 switch (BUSTYPE(sih
->bustype
)) {
1936 /* pcie core doesn't have any mapping to control the xtal pu */
1940 in
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_IN
, sizeof(uint32
));
1941 out
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
));
1942 outen
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
, sizeof(uint32
));
1945 * Avoid glitching the clock if GPRS is already using it.
1946 * We can't actually read the state of the PLLPD so we infer it
1947 * by the value of XTAL_PU which *is* readable via gpioin.
1949 if (on
&& (in
& PCI_CFG_GPIO_XTAL
))
1953 outen
|= PCI_CFG_GPIO_XTAL
;
1955 outen
|= PCI_CFG_GPIO_PLL
;
1958 /* turn primary xtal on */
1960 out
|= PCI_CFG_GPIO_XTAL
;
1962 out
|= PCI_CFG_GPIO_PLL
;
1963 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
,
1964 sizeof(uint32
), out
);
1965 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
,
1966 sizeof(uint32
), outen
);
1967 OSL_DELAY(XTAL_ON_DELAY
);
1972 out
&= ~PCI_CFG_GPIO_PLL
;
1973 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
,
1974 sizeof(uint32
), out
);
1979 out
&= ~PCI_CFG_GPIO_XTAL
;
1981 out
|= PCI_CFG_GPIO_PLL
;
1982 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
), out
);
1983 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
, sizeof(uint32
),
1993 * clock control policy function throught chipcommon
1995 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1996 * returns true if we are forcing fast clock
1997 * this is a wrapper over the next internal function
1998 * to allow flexible policy settings for outside caller
2001 si_clkctl_cc(si_t
*sih
, uint mode
)
2007 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2011 if (PCI_FORCEHT(sii
))
2012 return (mode
== CLK_FAST
);
2014 return _si_clkctl_cc(sii
, mode
);
2017 /* clk control mechanism through chipcommon, no policy checking */
2019 _si_clkctl_cc(si_info_t
*sii
, uint mode
)
2025 bool fast
= SI_FAST(sii
);
2027 /* chipcommon cores prior to rev6 don't support dynamic clock control */
2028 if (sii
->pub
.ccrev
< 6)
2031 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
2032 ASSERT(sii
->pub
.ccrev
!= 10);
2035 INTR_OFF(sii
, intr_val
);
2036 origidx
= sii
->curidx
;
2038 if ((BUSTYPE(sii
->pub
.bustype
) == SI_BUS
) &&
2039 si_setcore(&sii
->pub
, MIPS33_CORE_ID
, 0) &&
2040 (si_corerev(&sii
->pub
) <= 7) && (sii
->pub
.ccrev
>= 10))
2043 cc
= (chipcregs_t
*) si_setcore(&sii
->pub
, CC_CORE_ID
, 0);
2044 } else if ((cc
= (chipcregs_t
*) CCREGS_FAST(sii
)) == NULL
)
2048 if (!CCCTL_ENAB(&sii
->pub
) && (sii
->pub
.ccrev
< 20))
2052 case CLK_FAST
: /* FORCEHT, fast (pll) clock */
2053 if (sii
->pub
.ccrev
< 10) {
2054 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2055 si_clkctl_xtal(&sii
->pub
, XTAL
, ON
);
2056 SET_REG(sii
->osh
, &cc
->slow_clk_ctl
, (SCC_XC
| SCC_FS
| SCC_IP
), SCC_IP
);
2057 } else if (sii
->pub
.ccrev
< 20) {
2058 OR_REG(sii
->osh
, &cc
->system_clk_ctl
, SYCC_HR
);
2060 OR_REG(sii
->osh
, &cc
->clk_ctl_st
, CCS_FORCEHT
);
2063 /* wait for the PLL */
2064 if (PMUCTL_ENAB(&sii
->pub
)) {
2065 uint32 htavail
= CCS_HTAVAIL
;
2066 if (CHIPID(sii
->pub
.chip
) == BCM4328_CHIP_ID
)
2067 htavail
= CCS0_HTAVAIL
;
2068 SPINWAIT(((R_REG(sii
->osh
, &cc
->clk_ctl_st
) & htavail
) == 0),
2069 PMU_MAX_TRANSITION_DLY
);
2070 ASSERT(R_REG(sii
->osh
, &cc
->clk_ctl_st
) & htavail
);
2072 OSL_DELAY(PLL_DELAY
);
2076 case CLK_DYNAMIC
: /* enable dynamic clock control */
2077 if (sii
->pub
.ccrev
< 10) {
2078 scc
= R_REG(sii
->osh
, &cc
->slow_clk_ctl
);
2079 scc
&= ~(SCC_FS
| SCC_IP
| SCC_XC
);
2080 if ((scc
& SCC_SS_MASK
) != SCC_SS_XTAL
)
2082 W_REG(sii
->osh
, &cc
->slow_clk_ctl
, scc
);
2084 /* for dynamic control, we have to release our xtal_pu "force on" */
2086 si_clkctl_xtal(&sii
->pub
, XTAL
, OFF
);
2087 } else if (sii
->pub
.ccrev
< 20) {
2089 AND_REG(sii
->osh
, &cc
->system_clk_ctl
, ~SYCC_HR
);
2091 AND_REG(sii
->osh
, &cc
->clk_ctl_st
, ~CCS_FORCEHT
);
2101 si_setcoreidx(&sii
->pub
, origidx
);
2102 INTR_RESTORE(sii
, intr_val
);
2104 return (mode
== CLK_FAST
);
2107 /* Build device path. Support SI, PCI, and JTAG for now. */
2109 BCMNMIATTACHFN(si_devpath
)(si_t
*sih
, char *path
, int size
)
2113 ASSERT(path
!= NULL
);
2114 ASSERT(size
>= SI_DEVPATH_BUFSZ
);
2116 if (!path
|| size
<= 0)
2119 switch (BUSTYPE(sih
->bustype
)) {
2122 slen
= snprintf(path
, (size_t)size
, "sb/%u/", si_coreidx(sih
));
2125 ASSERT((SI_INFO(sih
))->osh
!= NULL
);
2126 slen
= snprintf(path
, (size_t)size
, "pci/%u/%u/",
2127 OSL_PCI_BUS((SI_INFO(sih
))->osh
),
2128 OSL_PCI_SLOT((SI_INFO(sih
))->osh
));
2131 SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
2132 SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
2133 slen
= snprintf(path
, (size_t)size
, "pc/1/1/");
2141 if (slen
< 0 || slen
>= size
) {
2150 BCMATTACHFN(si_coded_devpathvar
)(si_t
*sih
, char *varname
, int var_len
, const char *name
)
2152 char pathname
[SI_DEVPATH_BUFSZ
+ 32];
2153 char devpath
[SI_DEVPATH_BUFSZ
+ 32];
2158 /* try to get compact devpath if it exist */
2159 if (si_devpath(sih
, devpath
, SI_DEVPATH_BUFSZ
) == 0) {
2160 len
= strlen(devpath
);
2161 devpath
[len
- 1] = '\0';
2162 for (idx
= 0; idx
< SI_MAXCORES
; idx
++) {
2163 snprintf(pathname
, SI_DEVPATH_BUFSZ
, "devpath%d", idx
);
2164 if ((p
= getvar(NULL
, pathname
)) == NULL
)
2167 if (strncmp(p
, devpath
, len
) == 0) {
2168 snprintf(varname
, var_len
, "%d:%s", idx
, name
);
2177 /* Get a variable, but only if it has a devpath prefix */
2179 BCMATTACHFN(si_getdevpathvar
)(si_t
*sih
, const char *name
)
2181 char varname
[SI_DEVPATH_BUFSZ
+ 32];
2184 si_devpathvar(sih
, varname
, sizeof(varname
), name
);
2186 if ((val
= getvar(NULL
, varname
)) != NULL
)
2189 /* try to get compact devpath if it exist */
2190 if (si_coded_devpathvar(sih
, varname
, sizeof(varname
), name
) == NULL
)
2193 return (getvar(NULL
, varname
));
2196 /* Get a variable, but only if it has a devpath prefix */
2198 BCMATTACHFN(si_getdevpathintvar
)(si_t
*sih
, const char *name
)
2200 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
2201 return (getintvar(NULL
, name
));
2203 char varname
[SI_DEVPATH_BUFSZ
+ 32];
2206 si_devpathvar(sih
, varname
, sizeof(varname
), name
);
2208 if ((val
= getintvar(NULL
, varname
)) != 0)
2211 /* try to get compact devpath if it exist */
2212 if (si_coded_devpathvar(sih
, varname
, sizeof(varname
), name
) == NULL
)
2215 return (getintvar(NULL
, varname
));
2216 #endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
2221 si_getnvramflvar(si_t
*sih
, const char *name
)
2223 return (getvar(NULL
, name
));
2225 #endif /* DONGLEBUILD */
2227 /* Concatenate the dev path with a varname into the given 'var' buffer
2228 * and return the 'var' pointer.
2229 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
2230 * On overflow, the first char will be set to '\0'.
2233 BCMATTACHFN(si_devpathvar
)(si_t
*sih
, char *var
, int len
, const char *name
)
2237 if (!var
|| len
<= 0)
2240 if (si_devpath(sih
, var
, len
) == 0) {
2241 path_len
= strlen(var
);
2243 if (strlen(name
) + 1 > (uint
)(len
- path_len
))
2246 strncpy(var
+ path_len
, name
, len
- path_len
- 1);
2254 si_pciereg(si_t
*sih
, uint32 offset
, uint32 mask
, uint32 val
, uint type
)
2261 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__
));
2265 return pcicore_pciereg(sii
->pch
, offset
, mask
, val
, type
);
2269 si_pcieserdesreg(si_t
*sih
, uint32 mdioslave
, uint32 offset
, uint32 mask
, uint32 val
)
2276 SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__
));
2280 return pcicore_pcieserdesreg(sii
->pch
, mdioslave
, offset
, mask
, val
);
2284 /* return TRUE if PCIE capability exists in the pci config space */
2286 si_ispcie(si_info_t
*sii
)
2290 if (BUSTYPE(sii
->pub
.bustype
) != PCI_BUS
)
2293 cap_ptr
= pcicore_find_pci_capability(sii
->osh
, PCI_CAP_PCIECAP_ID
, NULL
, NULL
);
2300 /* Wake-on-wireless-LAN (WOWL) support functions */
2301 /* Enable PME generation and disable clkreq */
2303 si_pci_pmeen(si_t
*sih
)
2309 pcicore_pmeen(sii
->pch
);
2312 /* Return TRUE if PME status is set */
2314 si_pci_pmestat(si_t
*sih
)
2320 return pcicore_pmestat(sii
->pch
);
2323 /* Disable PME generation, clear the PME status bit if set */
2325 si_pci_pmeclr(si_t
*sih
)
2331 pcicore_pmeclr(sii
->pch
);
2334 /* initialize the pcmcia core */
2336 si_pcmcia_init(si_t
*sih
)
2343 /* enable d11 mac interrupts */
2344 OSL_PCMCIA_READ_ATTR(sii
->osh
, PCMCIA_FCR0
+ PCMCIA_COR
, &cor
, 1);
2345 cor
|= COR_IRQEN
| COR_FUNEN
;
2346 OSL_PCMCIA_WRITE_ATTR(sii
->osh
, PCMCIA_FCR0
+ PCMCIA_COR
, &cor
, 1);
2352 BCMATTACHFN(si_pci_war16165
)(si_t
*sih
)
2358 return (PCI(sii
) && (sih
->buscorerev
<= 10));
2361 /* Disable pcie_war_ovr for some platforms (sigh!)
2362 * This is for boards that have BFL2_PCIEWAR_OVR set
2363 * but are in systems that still want the benefits of ASPM
2364 * Note that this should be done AFTER si_doattach
2367 si_pcie_war_ovr_update(si_t
*sih
, uint8 aspm
)
2376 pcie_war_ovr_aspm_update(sii
->pch
, aspm
);
2380 si_pcie_power_save_enable(si_t
*sih
, bool enable
)
2389 pcie_power_save_enable(sii
->pch
, enable
);
2393 si_pcie_set_request_size(si_t
*sih
, uint16 size
)
2402 pcie_set_request_size(sii
->pch
, size
);
2406 si_pcie_get_request_size(si_t
*sih
)
2415 return pcie_get_request_size(sii
->pch
);
2418 /* back door for other module to override chippkg */
2420 si_chippkg_set(si_t
*sih
, uint val
)
2426 sii
->pub
.chippkg
= val
;
2430 BCMINITFN(si_pci_up
)(si_t
*sih
)
2436 /* if not pci bus, we're done */
2437 if (BUSTYPE(sih
->bustype
) != PCI_BUS
)
2440 if (PCI_FORCEHT(sii
))
2441 _si_clkctl_cc(sii
, CLK_FAST
);
2444 pcicore_up(sii
->pch
, SI_PCIUP
);
2445 if (((CHIPID(sih
->chip
) == BCM4311_CHIP_ID
) && (CHIPREV(sih
->chiprev
) == 2)) ||
2446 (CHIPID(sih
->chip
) == BCM4312_CHIP_ID
))
2447 sb_set_initiator_to((void *)sii
, 0x3,
2448 si_findcoreidx((void *)sii
, D11_CORE_ID
, 0));
2452 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2454 BCMUNINITFN(si_pci_sleep
)(si_t
*sih
)
2460 pcicore_sleep(sii
->pch
);
2463 /* Unconfigure and/or apply various WARs when going down */
2465 BCMINITFN(si_pci_down
)(si_t
*sih
)
2471 /* if not pci bus, we're done */
2472 if (BUSTYPE(sih
->bustype
) != PCI_BUS
)
2475 /* release FORCEHT since chip is going to "down" state */
2476 if (PCI_FORCEHT(sii
))
2477 _si_clkctl_cc(sii
, CLK_DYNAMIC
);
2479 pcicore_down(sii
->pch
, SI_PCIDOWN
);
2483 * Configure the pci core for pci client (NIC) action
2484 * coremask is the bitvec of cores by index to be enabled.
2487 BCMATTACHFN(si_pci_setup
)(si_t
*sih
, uint coremask
)
2490 sbpciregs_t
*pciregs
= NULL
;
2491 uint32 siflag
= 0, w
;
2496 if (BUSTYPE(sii
->pub
.bustype
) != PCI_BUS
)
2499 ASSERT(PCI(sii
) || PCIE(sii
));
2500 ASSERT(sii
->pub
.buscoreidx
!= BADIDX
);
2503 /* get current core index */
2506 /* we interrupt on this backplane flag number */
2507 siflag
= si_flag(sih
);
2509 /* switch over to pci core */
2510 pciregs
= (sbpciregs_t
*)si_setcoreidx(sih
, sii
->pub
.buscoreidx
);
2514 * Enable sb->pci interrupts. Assume
2515 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2517 if (PCIE(sii
) || (PCI(sii
) && ((sii
->pub
.buscorerev
) >= 6))) {
2518 /* pci config write to set this core bit in PCIIntMask */
2519 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_INT_MASK
, sizeof(uint32
));
2520 w
|= (coremask
<< PCI_SBIM_SHIFT
);
2522 /* User mode operate with interrupt disabled */
2523 w
&= !(coremask
<< PCI_SBIM_SHIFT
);
2525 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_INT_MASK
, sizeof(uint32
), w
);
2527 /* set sbintvec bit for our flag number */
2528 si_setint(sih
, siflag
);
2532 OR_REG(sii
->osh
, &pciregs
->sbtopci2
, (SBTOPCI_PREF
| SBTOPCI_BURST
));
2533 if (sii
->pub
.buscorerev
>= 11) {
2534 OR_REG(sii
->osh
, &pciregs
->sbtopci2
, SBTOPCI_RC_READMULTI
);
2535 w
= R_REG(sii
->osh
, &pciregs
->clkrun
);
2536 W_REG(sii
->osh
, &pciregs
->clkrun
, (w
| PCI_CLKRUN_DSBL
));
2537 w
= R_REG(sii
->osh
, &pciregs
->clkrun
);
2540 /* switch back to previous core */
2541 si_setcoreidx(sih
, idx
);
2546 si_pcieclkreq(si_t
*sih
, uint32 mask
, uint32 val
)
2554 return pcie_clkreq(sii
->pch
, mask
, val
);
2558 si_pcielcreg(si_t
*sih
, uint32 mask
, uint32 val
)
2567 return pcie_lcreg(sii
->pch
, mask
, val
);
2570 /* indirect way to read pcie config regs */
2572 si_pcie_readreg(void *sih
, uint addrtype
, uint offset
)
2574 return pcie_readreg(((si_info_t
*)sih
)->osh
, (sbpcieregs_t
*)PCIEREGS(((si_info_t
*)sih
)),
2580 * Fixup SROMless PCI device's configuration.
2581 * The current core may be changed upon return.
2584 si_pci_fixcfg(si_t
*sih
)
2586 uint origidx
, pciidx
;
2587 sbpciregs_t
*pciregs
= NULL
;
2588 sbpcieregs_t
*pcieregs
= NULL
;
2590 uint16 val16
, *reg16
= NULL
;
2593 si_info_t
*sii
= SI_INFO(sih
);
2595 ASSERT(BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
);
2597 if ((CHIPID(sii
->pub
.chip
) == BCM4321_CHIP_ID
) && (CHIPREV(sii
->pub
.chiprev
) < 2)) {
2598 w
= (CHIPREV(sii
->pub
.chiprev
) == 0) ?
2599 CHIPCTRL_4321A0_DEFAULT
: CHIPCTRL_4321A1_DEFAULT
;
2600 si_corereg(&sii
->pub
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, chipcontrol
), ~0, w
);
2603 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2604 /* save the current index */
2605 origidx
= si_coreidx(&sii
->pub
);
2607 /* check 'pi' is correct and fix it if not */
2608 if (sii
->pub
.buscoretype
== PCIE_CORE_ID
) {
2609 pcieregs
= (sbpcieregs_t
*)si_setcore(&sii
->pub
, PCIE_CORE_ID
, 0);
2611 ASSERT(pcieregs
!= NULL
);
2612 reg16
= &pcieregs
->sprom
[SRSH_PI_OFFSET
];
2613 } else if (sii
->pub
.buscoretype
== PCI_CORE_ID
) {
2614 pciregs
= (sbpciregs_t
*)si_setcore(&sii
->pub
, PCI_CORE_ID
, 0);
2616 ASSERT(pciregs
!= NULL
);
2617 reg16
= &pciregs
->sprom
[SRSH_PI_OFFSET
];
2619 pciidx
= si_coreidx(&sii
->pub
);
2620 val16
= R_REG(sii
->osh
, reg16
);
2621 if (((val16
& SRSH_PI_MASK
) >> SRSH_PI_SHIFT
) != (uint16
)pciidx
) {
2622 val16
= (uint16
)(pciidx
<< SRSH_PI_SHIFT
) | (val16
& ~SRSH_PI_MASK
);
2623 W_REG(sii
->osh
, reg16
, val16
);
2626 /* restore the original index */
2627 si_setcoreidx(&sii
->pub
, origidx
);
2629 pcicore_hwup(sii
->pch
);
2633 #if defined(BCMDBG_DUMP)
2636 si_dump(si_t
*sih
, struct bcmstrbuf
*b
)
2643 bcm_bprintf(b
, "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n",
2644 sii
, sih
->chip
, sih
->chiprev
, sih
->boardtype
, sih
->boardvendor
, sih
->bustype
);
2645 bcm_bprintf(b
, "osh %p curmap %p\n",
2646 sii
->osh
, sii
->curmap
);
2647 if (CHIPTYPE(sih
->socitype
) == SOCI_SB
)
2648 bcm_bprintf(b
, "sonicsrev %d ", sih
->socirev
);
2649 bcm_bprintf(b
, "ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n",
2650 sih
->ccrev
, sih
->buscoretype
, sih
->buscorerev
, sii
->curidx
);
2653 if ((BUSTYPE(sih
->bustype
) == PCI_BUS
) && (sii
->pch
))
2654 pcicore_dump(sii
->pch
, b
);
2657 bcm_bprintf(b
, "cores: ");
2658 for (i
= 0; i
< sii
->numcores
; i
++)
2659 bcm_bprintf(b
, "0x%x ", sii
->coreid
[i
]);
2660 bcm_bprintf(b
, "\n");
2664 si_ccreg_dump(si_t
*sih
, struct bcmstrbuf
*b
)
2668 uint i
, intr_val
= 0;
2672 origidx
= sii
->curidx
;
2674 /* only support corerev 22 for now */
2675 if (sih
->ccrev
!= 23)
2678 INTR_OFF(sii
, intr_val
);
2680 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
2682 bcm_bprintf(b
, "\n===cc(rev %d) registers(offset val)===\n", sih
->ccrev
);
2683 for (i
= 0; i
<= 0xc4; i
+= 4) {
2685 bcm_bprintf(b
, "\n");
2688 bcm_bprintf(b
, "0x%x\t0x%x\n", i
, *(uint32
*)((uintptr
)cc
+ i
));
2691 bcm_bprintf(b
, "\n");
2693 for (i
= 0x1e0; i
<= 0x1e4; i
+= 4) {
2694 bcm_bprintf(b
, "0x%x\t0x%x\n", i
, *(uint32
*)((uintptr
)cc
+ i
));
2696 bcm_bprintf(b
, "\n");
2698 if (sih
->cccaps
& CC_CAP_PMU
) {
2699 for (i
= 0x600; i
<= 0x660; i
+= 4) {
2700 bcm_bprintf(b
, "0x%x\t0x%x\n", i
, *(uint32
*)((uintptr
)cc
+ i
));
2703 bcm_bprintf(b
, "\n");
2705 si_setcoreidx(sih
, origidx
);
2706 INTR_RESTORE(sii
, intr_val
);
2709 /* dump dynamic clock control related registers */
2711 si_clkctl_dump(si_t
*sih
, struct bcmstrbuf
*b
)
2718 if (!(sih
->cccaps
& CC_CAP_PWR_CTL
))
2722 INTR_OFF(sii
, intr_val
);
2723 origidx
= sii
->curidx
;
2724 if ((cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
2727 bcm_bprintf(b
, "pll_on_delay 0x%x fref_sel_delay 0x%x ",
2728 cc
->pll_on_delay
, cc
->fref_sel_delay
);
2729 if ((sih
->ccrev
>= 6) && (sih
->ccrev
< 10))
2730 bcm_bprintf(b
, "slow_clk_ctl 0x%x ", cc
->slow_clk_ctl
);
2731 if (sih
->ccrev
>= 10) {
2732 bcm_bprintf(b
, "system_clk_ctl 0x%x ", cc
->system_clk_ctl
);
2733 bcm_bprintf(b
, "clkstatestretch 0x%x ", cc
->clkstatestretch
);
2736 if (BUSTYPE(sih
->bustype
) == PCI_BUS
)
2737 bcm_bprintf(b
, "gpioout 0x%x gpioouten 0x%x ",
2738 OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
)),
2739 OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
, sizeof(uint32
)));
2741 if (sih
->cccaps
& CC_CAP_PMU
) {
2742 /* dump some PMU register ? */
2744 bcm_bprintf(b
, "\n");
2746 si_setcoreidx(sih
, origidx
);
2748 INTR_RESTORE(sii
, intr_val
);
2752 si_dump_pcieregs(si_t
*sih
, struct bcmstrbuf
*b
)
2761 return pcicore_dump_pcieregs(sii
->pch
, b
);
2765 si_gpiodump(si_t
*sih
, struct bcmstrbuf
*b
)
2774 INTR_OFF(sii
, intr_val
);
2776 origidx
= si_coreidx(sih
);
2778 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
2781 bcm_bprintf(b
, "GPIOregs\t");
2783 bcm_bprintf(b
, "gpioin 0x%x ", R_REG(sii
->osh
, &cc
->gpioin
));
2784 bcm_bprintf(b
, "gpioout 0x%x ", R_REG(sii
->osh
, &cc
->gpioout
));
2785 bcm_bprintf(b
, "gpioouten 0x%x ", R_REG(sii
->osh
, &cc
->gpioouten
));
2786 bcm_bprintf(b
, "gpiocontrol 0x%x ", R_REG(sii
->osh
, &cc
->gpiocontrol
));
2787 bcm_bprintf(b
, "gpiointpolarity 0x%x ", R_REG(sii
->osh
, &cc
->gpiointpolarity
));
2788 bcm_bprintf(b
, "gpiointmask 0x%x ", R_REG(sii
->osh
, &cc
->gpiointmask
));
2790 if (sii
->pub
.ccrev
>= 16) {
2791 bcm_bprintf(b
, "gpiotimerval 0x%x ", R_REG(sii
->osh
, &cc
->gpiotimerval
));
2792 bcm_bprintf(b
, "gpiotimeroutmask 0x%x", R_REG(sii
->osh
, &cc
->gpiotimeroutmask
));
2794 bcm_bprintf(b
, "\n");
2796 /* restore the original index */
2797 si_setcoreidx(sih
, origidx
);
2799 INTR_RESTORE(sii
, intr_val
);
2805 /* change logical "focus" to the gpio core for optimized access */
2807 si_gpiosetcore(si_t
*sih
)
2809 return (si_setcoreidx(sih
, SI_CC_IDX
));
2812 /* mask&set gpiocontrol bits */
2814 si_gpiocontrol(si_t
*sih
, uint32 mask
, uint32 val
, uint8 priority
)
2820 /* gpios could be shared on router platforms
2821 * ignore reservation if it's high priority (e.g., test apps)
2823 if ((priority
!= GPIO_HI_PRIORITY
) &&
2824 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2825 mask
= priority
? (si_gpioreservation
& mask
) :
2826 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2830 regoff
= OFFSETOF(chipcregs_t
, gpiocontrol
);
2831 return (si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
));
2834 /* mask&set gpio output enable bits */
2836 si_gpioouten(si_t
*sih
, uint32 mask
, uint32 val
, uint8 priority
)
2842 /* gpios could be shared on router platforms
2843 * ignore reservation if it's high priority (e.g., test apps)
2845 if ((priority
!= GPIO_HI_PRIORITY
) &&
2846 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2847 mask
= priority
? (si_gpioreservation
& mask
) :
2848 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2852 regoff
= OFFSETOF(chipcregs_t
, gpioouten
);
2853 return (si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
));
2856 /* mask&set gpio output bits */
2858 si_gpioout(si_t
*sih
, uint32 mask
, uint32 val
, uint8 priority
)
2864 /* gpios could be shared on router platforms
2865 * ignore reservation if it's high priority (e.g., test apps)
2867 if ((priority
!= GPIO_HI_PRIORITY
) &&
2868 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2869 mask
= priority
? (si_gpioreservation
& mask
) :
2870 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2874 regoff
= OFFSETOF(chipcregs_t
, gpioout
);
2875 return (si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
));
2878 /* reserve one gpio */
2880 si_gpioreserve(si_t
*sih
, uint32 gpio_bitmask
, uint8 priority
)
2886 /* only cores on SI_BUS share GPIO's and only applcation users need to
2887 * reserve/release GPIO
2889 if ((BUSTYPE(sih
->bustype
) != SI_BUS
) || (!priority
)) {
2890 ASSERT((BUSTYPE(sih
->bustype
) == SI_BUS
) && (priority
));
2893 /* make sure only one bit is set */
2894 if ((!gpio_bitmask
) || ((gpio_bitmask
) & (gpio_bitmask
- 1))) {
2895 ASSERT((gpio_bitmask
) && !((gpio_bitmask
) & (gpio_bitmask
- 1)));
2899 /* already reserved */
2900 if (si_gpioreservation
& gpio_bitmask
)
2902 /* set reservation */
2903 si_gpioreservation
|= gpio_bitmask
;
2905 return si_gpioreservation
;
2908 /* release one gpio */
2910 * releasing the gpio doesn't change the current value on the GPIO last write value
2911 * persists till some one overwrites it
2915 si_gpiorelease(si_t
*sih
, uint32 gpio_bitmask
, uint8 priority
)
2921 /* only cores on SI_BUS share GPIO's and only applcation users need to
2922 * reserve/release GPIO
2924 if ((BUSTYPE(sih
->bustype
) != SI_BUS
) || (!priority
)) {
2925 ASSERT((BUSTYPE(sih
->bustype
) == SI_BUS
) && (priority
));
2928 /* make sure only one bit is set */
2929 if ((!gpio_bitmask
) || ((gpio_bitmask
) & (gpio_bitmask
- 1))) {
2930 ASSERT((gpio_bitmask
) && !((gpio_bitmask
) & (gpio_bitmask
- 1)));
2934 /* already released */
2935 if (!(si_gpioreservation
& gpio_bitmask
))
2938 /* clear reservation */
2939 si_gpioreservation
&= ~gpio_bitmask
;
2941 return si_gpioreservation
;
2944 /* return the current gpioin register value */
2946 si_gpioin(si_t
*sih
)
2954 regoff
= OFFSETOF(chipcregs_t
, gpioin
);
2955 return (si_corereg(sih
, SI_CC_IDX
, regoff
, 0, 0));
2958 /* mask&set gpio interrupt polarity bits */
2960 si_gpiointpolarity(si_t
*sih
, uint32 mask
, uint32 val
, uint8 priority
)
2968 /* gpios could be shared on router platforms */
2969 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2970 mask
= priority
? (si_gpioreservation
& mask
) :
2971 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2975 regoff
= OFFSETOF(chipcregs_t
, gpiointpolarity
);
2976 return (si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
));
2979 /* mask&set gpio interrupt mask bits */
2981 si_gpiointmask(si_t
*sih
, uint32 mask
, uint32 val
, uint8 priority
)
2989 /* gpios could be shared on router platforms */
2990 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2991 mask
= priority
? (si_gpioreservation
& mask
) :
2992 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2996 regoff
= OFFSETOF(chipcregs_t
, gpiointmask
);
2997 return (si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
));
3000 /* assign the gpio to an led */
3002 si_gpioled(si_t
*sih
, uint32 mask
, uint32 val
)
3007 if (sih
->ccrev
< 16)
3010 /* gpio led powersave reg */
3011 return (si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, gpiotimeroutmask
), mask
, val
));
3014 /* mask&set gpio timer val */
3016 si_gpiotimerval(si_t
*sih
, uint32 mask
, uint32 gpiotimerval
)
3022 if (sih
->ccrev
< 16)
3025 return (si_corereg(sih
, SI_CC_IDX
,
3026 OFFSETOF(chipcregs_t
, gpiotimerval
), mask
, gpiotimerval
));
3030 si_gpiopull(si_t
*sih
, bool updown
, uint32 mask
, uint32 val
)
3036 if (sih
->ccrev
< 20)
3039 offs
= (updown
? OFFSETOF(chipcregs_t
, gpiopulldown
) : OFFSETOF(chipcregs_t
, gpiopullup
));
3040 return (si_corereg(sih
, SI_CC_IDX
, offs
, mask
, val
));
3044 si_gpioevent(si_t
*sih
, uint regtype
, uint32 mask
, uint32 val
)
3050 if (sih
->ccrev
< 11)
3053 if (regtype
== GPIO_REGEVT
)
3054 offs
= OFFSETOF(chipcregs_t
, gpioevent
);
3055 else if (regtype
== GPIO_REGEVT_INTMSK
)
3056 offs
= OFFSETOF(chipcregs_t
, gpioeventintmask
);
3057 else if (regtype
== GPIO_REGEVT_INTPOL
)
3058 offs
= OFFSETOF(chipcregs_t
, gpioeventintpolarity
);
3062 return (si_corereg(sih
, SI_CC_IDX
, offs
, mask
, val
));
3066 BCMATTACHFN(si_gpio_handler_register
)(si_t
*sih
, uint32 event
,
3067 bool level
, gpio_handler_t cb
, void *arg
)
3076 if (sih
->ccrev
< 11)
3079 if ((gi
= MALLOC(sii
->osh
, sizeof(gpioh_item_t
))) == NULL
)
3082 bzero(gi
, sizeof(gpioh_item_t
));
3088 gi
->next
= sii
->gpioh_head
;
3089 sii
->gpioh_head
= gi
;
3093 gpioh_item_t
*h
= sii
->gpioh_head
;
3096 for (; h
; h
= h
->next
) {
3098 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3099 h
, h
->handler
, h
->event
));
3101 SI_ERROR(("gpiohdler total=%d\n", cnt
));
3104 return (void *)(gi
);
3108 BCMATTACHFN(si_gpio_handler_unregister
)(si_t
*sih
, void *gpioh
)
3111 gpioh_item_t
*p
, *n
;
3114 if (sih
->ccrev
< 11)
3117 ASSERT(sii
->gpioh_head
!= NULL
);
3118 if ((void*)sii
->gpioh_head
== gpioh
) {
3119 sii
->gpioh_head
= sii
->gpioh_head
->next
;
3120 MFREE(sii
->osh
, gpioh
, sizeof(gpioh_item_t
));
3123 p
= sii
->gpioh_head
;
3126 if ((void*)n
== gpioh
) {
3128 MFREE(sii
->osh
, gpioh
, sizeof(gpioh_item_t
));
3138 gpioh_item_t
*h
= sii
->gpioh_head
;
3141 for (; h
; h
= h
->next
) {
3143 SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
3144 h
, h
->handler
, h
->event
));
3146 SI_ERROR(("gpiohdler total=%d\n", cnt
));
3149 ASSERT(0); /* Not found in list */
3153 si_gpio_handler_process(si_t
*sih
)
3158 uint32 level
= si_gpioin(sih
);
3159 uint32 edge
= si_gpioevent(sih
, GPIO_REGEVT
, 0, 0);
3162 for (h
= sii
->gpioh_head
; h
!= NULL
; h
= h
->next
) {
3164 status
= (h
->level
? level
: edge
);
3166 if (status
& h
->event
)
3167 h
->handler(status
, h
->arg
);
3171 si_gpioevent(sih
, GPIO_REGEVT
, edge
, edge
); /* clear edge-trigger status */
3175 si_gpio_int_enable(si_t
*sih
, bool enable
)
3181 if (sih
->ccrev
< 11)
3184 offs
= OFFSETOF(chipcregs_t
, intmask
);
3185 return (si_corereg(sih
, SI_CC_IDX
, offs
, CI_GPIO
, (enable
? CI_GPIO
: 0)));
3189 /* Return the size of the specified SOCRAM bank */
3191 socram_banksize(si_info_t
*sii
, sbsocramregs_t
*regs
, uint8 index
, uint8 mem_type
)
3193 uint banksize
, bankinfo
;
3194 uint bankidx
= index
| (mem_type
<< SOCRAM_BANKIDX_MEMTYPE_SHIFT
);
3196 ASSERT(mem_type
<= SOCRAM_MEMTYPE_DEVRAM
);
3198 W_REG(sii
->osh
, ®s
->bankidx
, bankidx
);
3199 bankinfo
= R_REG(sii
->osh
, ®s
->bankinfo
);
3200 banksize
= SOCRAM_BANKINFO_SZBASE
* ((bankinfo
& SOCRAM_BANKINFO_SZMASK
) + 1);
3205 si_socdevram(si_t
*sih
, bool set
, uint8
*enable
, uint8
*protect
)
3210 sbsocramregs_t
*regs
;
3216 /* Block ints and save current core */
3217 INTR_OFF(sii
, intr_val
);
3218 origidx
= si_coreidx(sih
);
3221 *enable
= *protect
= 0;
3223 /* Switch to SOCRAM core */
3224 if (!(regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0)))
3227 /* Get info for determining size */
3228 if (!(wasup
= si_iscoreup(sih
)))
3229 si_core_reset(sih
, 0, 0);
3231 corerev
= si_corerev(sih
);
3232 if (corerev
>= 10) {
3236 uint32 bankidx
, bankinfo
;
3238 extcinfo
= R_REG(sii
->osh
, ®s
->extracoreinfo
);
3239 nb
= ((extcinfo
& SOCRAM_DEVRAMBANK_MASK
) >> SOCRAM_DEVRAMBANK_SHIFT
);
3240 for (i
= 0; i
< nb
; i
++) {
3241 bankidx
= i
| (SOCRAM_MEMTYPE_DEVRAM
<< SOCRAM_BANKIDX_MEMTYPE_SHIFT
);
3242 W_REG(sii
->osh
, ®s
->bankidx
, bankidx
);
3243 bankinfo
= R_REG(sii
->osh
, ®s
->bankinfo
);
3245 bankinfo
&= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK
;
3246 bankinfo
&= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK
;
3248 bankinfo
|= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT
);
3250 bankinfo
|= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT
);
3252 W_REG(sii
->osh
, ®s
->bankinfo
, bankinfo
);
3255 if (bankinfo
& SOCRAM_BANKINFO_DEVRAMSEL_MASK
) {
3257 if (bankinfo
& SOCRAM_BANKINFO_DEVRAMPRO_MASK
)
3264 /* Return to previous state and core */
3266 si_core_disable(sih
, 0);
3267 si_setcoreidx(sih
, origidx
);
3270 INTR_RESTORE(sii
, intr_val
);
3274 si_socdevram_pkg(si_t
*sih
)
3276 if (si_socdevram_size(sih
) > 0)
3283 si_socdevram_size(si_t
*sih
)
3289 sbsocramregs_t
*regs
;
3295 /* Block ints and save current core */
3296 INTR_OFF(sii
, intr_val
);
3297 origidx
= si_coreidx(sih
);
3299 /* Switch to SOCRAM core */
3300 if (!(regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0)))
3303 /* Get info for determining size */
3304 if (!(wasup
= si_iscoreup(sih
)))
3305 si_core_reset(sih
, 0, 0);
3307 corerev
= si_corerev(sih
);
3308 if (corerev
>= 10) {
3313 extcinfo
= R_REG(sii
->osh
, ®s
->extracoreinfo
);
3314 nb
= (((extcinfo
& SOCRAM_DEVRAMBANK_MASK
) >> SOCRAM_DEVRAMBANK_SHIFT
));
3315 for (i
= 0; i
< nb
; i
++)
3316 memsize
+= socram_banksize(sii
, regs
, i
, SOCRAM_MEMTYPE_DEVRAM
);
3319 /* Return to previous state and core */
3321 si_core_disable(sih
, 0);
3322 si_setcoreidx(sih
, origidx
);
3325 INTR_RESTORE(sii
, intr_val
);
3330 /* Return the RAM size of the SOCRAM core */
3332 si_socram_size(si_t
*sih
)
3338 sbsocramregs_t
*regs
;
3346 /* Block ints and save current core */
3347 INTR_OFF(sii
, intr_val
);
3348 origidx
= si_coreidx(sih
);
3350 /* Switch to SOCRAM core */
3351 if (!(regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0)))
3354 /* Get info for determining size */
3355 if (!(wasup
= si_iscoreup(sih
)))
3356 si_core_reset(sih
, 0, 0);
3357 corerev
= si_corerev(sih
);
3358 coreinfo
= R_REG(sii
->osh
, ®s
->coreinfo
);
3360 /* Calculate size from coreinfo based on rev */
3362 memsize
= 1 << (16 + (coreinfo
& SRCI_MS0_MASK
));
3363 else if (corerev
< 3) {
3364 memsize
= 1 << (SR_BSZ_BASE
+ (coreinfo
& SRCI_SRBSZ_MASK
));
3365 memsize
*= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
3366 } else if ((corerev
<= 7) || (corerev
== 12)) {
3367 uint nb
= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
3368 uint bsz
= (coreinfo
& SRCI_SRBSZ_MASK
);
3369 uint lss
= (coreinfo
& SRCI_LSS_MASK
) >> SRCI_LSS_SHIFT
;
3372 memsize
= nb
* (1 << (bsz
+ SR_BSZ_BASE
));
3374 memsize
+= (1 << ((lss
- 1) + SR_BSZ_BASE
));
3377 uint nb
= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
3378 for (i
= 0; i
< nb
; i
++)
3379 memsize
+= socram_banksize(sii
, regs
, i
, SOCRAM_MEMTYPE_RAM
);
3382 /* Return to previous state and core */
3384 si_core_disable(sih
, 0);
3385 si_setcoreidx(sih
, origidx
);
3388 INTR_RESTORE(sii
, intr_val
);
3394 #define NOTIFY_BT_FM_DISABLE(sih, val) \
3395 si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
3396 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
3398 /* Query OTP to see if FM is disabled */
3400 BCMATTACHFN(si_query_FMDisabled_from_OTP
)(si_t
*sih
, uint16
*FMDisabled
)
3402 int error
= BCME_OK
;
3407 /* Determine the bit for the chip */
3408 switch (CHIPID(sih
->chip
)) {
3409 case BCM4325_CHIP_ID
:
3410 if (CHIPREV(sih
->chiprev
) >= 6)
3411 bitoff
= OTP4325_FM_DISABLED_OFFSET
;
3417 /* If there is a bit for this chip, check it */
3419 if (!(wasup
= si_is_otp_powered(sih
))) {
3420 si_otp_power(sih
, TRUE
);
3423 if ((oh
= otp_init(sih
)) != NULL
)
3424 *FMDisabled
= !otp_read_bit(oh
, OTP4325_FM_DISABLED_OFFSET
);
3426 error
= BCME_NOTFOUND
;
3429 si_otp_power(sih
, FALSE
);
3439 return (!!(sih
->cccaps
& CC_CAP_ECI
));
3445 return (sih
->cccaps_ext
& CC_CAP_EXT_SECI_PRESENT
);
3448 /* ECI Init routine */
3450 BCMATTACHFN(si_eci_init
)(si_t
*sih
)
3456 uint16 FMDisabled
= FALSE
;
3458 /* check for ECI capability */
3459 if (!(sih
->cccaps
& CC_CAP_ECI
))
3463 fast
= SI_FAST(sii
);
3465 origidx
= sii
->curidx
;
3466 if ((cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
3468 } else if ((cc
= (chipcregs_t
*)CCREGS_FAST(sii
)) == NULL
)
3472 /* disable level based interrupts */
3473 if (sih
->ccrev
< 35) {
3474 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_intmaskhi
, 0x0);
3475 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_intmaskmi
, 0x0);
3476 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_intmasklo
, 0x0);
3479 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_intmaskhi
, 0x0);
3480 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_intmasklo
, 0x0);
3483 /* Assign eci_output bits between 'wl' and dot11mac */
3484 if (sih
->ccrev
< 35) {
3485 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_control
, ECI_MACCTRL_BITS
);
3488 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_controllo
, ECI_MACCTRLLO_BITS
);
3489 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_controlhi
, ECI_MACCTRLHI_BITS
);
3492 /* enable only edge based interrupts
3493 * only toggle on bit 62 triggers an interrupt
3495 if (sih
->ccrev
< 35) {
3496 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_eventmaskhi
, 0x0);
3497 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_eventmaskmi
, 0x0);
3498 W_REG(sii
->osh
, &cc
->eci
.lt35
.eci_eventmasklo
, 0x0);
3501 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_eventmaskhi
, 0x0);
3502 W_REG(sii
->osh
, &cc
->eci
.ge35
.eci_eventmasklo
, 0x0);
3505 /* restore previous core */
3507 si_setcoreidx(sih
, origidx
);
3509 /* if FM disabled in OTP, let BT know */
3510 if (!si_query_FMDisabled_from_OTP(sih
, &FMDisabled
)) {
3512 NOTIFY_BT_FM_DISABLE(sih
, 1);
3520 * Write values to BT on eci_output.
3523 si_eci_notify_bt(si_t
*sih
, uint32 mask
, uint32 val
, bool interrupt
)
3527 /* Nothing to do if there is no eci */
3528 if ((sih
->cccaps
& CC_CAP_ECI
) == 0)
3531 /* Clear interrupt bit by default */
3533 si_corereg(sih
, SI_CC_IDX
, (sih
->ccrev
< 35 ?
3534 OFFSETOF(chipcregs_t
, eci
.lt35
.eci_output
) :
3535 OFFSETOF(chipcregs_t
, eci
.ge35
.eci_outputlo
)),
3538 if (sih
->ccrev
>= 35) {
3539 if ((mask
& 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD
) {
3540 offset
= OFFSETOF(chipcregs_t
, eci
.ge35
.eci_outputhi
);
3541 mask
= mask
& ~0xFFFF0000;
3544 offset
= OFFSETOF(chipcregs_t
, eci
.ge35
.eci_outputlo
);
3545 mask
= mask
| (1<<30);
3546 val
= val
& ~(1 << 30);
3550 offset
= OFFSETOF(chipcregs_t
, eci
.lt35
.eci_output
);
3551 val
= val
& ~(1 << 30);
3554 si_corereg(sih
, SI_CC_IDX
, offset
, mask
, val
);
3556 /* Set interrupt bit if needed */
3558 si_corereg(sih
, SI_CC_IDX
,
3560 OFFSETOF(chipcregs_t
, eci
.lt35
.eci_output
) :
3561 OFFSETOF(chipcregs_t
, eci
.ge35
.eci_outputlo
)),
3562 (1 << 30), (1 << 30));
3565 /* seci clock enable/disable */
3567 si_seci_clkreq(si_t
*sih
, bool enable
)
3577 val
= CLKCTL_STS_SECI_CLK_REQ
;
3581 offset
= OFFSETOF(chipcregs_t
, clk_ctl_st
);
3583 si_corereg(sih
, SI_CC_IDX
, offset
, CLKCTL_STS_SECI_CLK_REQ
, val
);
3588 SPINWAIT((si_corereg(sih
, 0, offset
, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL
), 100000);
3590 clk_ctl_st
= si_corereg(sih
, 0, offset
, 0, 0);
3592 if (!(clk_ctl_st
& CLKCTL_STS_SECI_CLK_AVAIL
)) {
3593 SI_ERROR(("SECI clock is still not available\n"));
3600 BCMINITFN(si_seci_down
)(si_t
*sih
)
3612 fast
= SI_FAST(sii
);
3615 origidx
= sii
->curidx
;
3616 if ((cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
3618 } else if ((cc
= (chipcregs_t
*)CCREGS_FAST(sii
)) == NULL
)
3622 /* put seci in reset */
3623 seci_conf
= R_REG(sii
->osh
, &cc
->SECI_config
);
3624 seci_conf
&= ~SECI_ENAB_SECI_ECI
;
3625 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3626 seci_conf
|= SECI_RESET
;
3627 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3629 /* bring down the clock if up */
3630 si_seci_clkreq(sih
, FALSE
);
3632 /* restore previous core */
3634 si_setcoreidx(sih
, origidx
);
3637 /* SECI Init routine, pass in seci_mode */
3639 BCMINITFN(si_seci_init
)(si_t
*sih
, uint8 seci_mode
)
3650 if (sih
->ccrev
< 35)
3656 if (seci_mode
> SECI_MODE_MASK
)
3660 fast
= SI_FAST(sii
);
3662 origidx
= sii
->curidx
;
3663 if ((ptr
= si_setcore(sih
, CC_CORE_ID
, 0)) == NULL
)
3665 } else if ((ptr
= CCREGS_FAST(sii
)) == NULL
)
3667 cc
= (chipcregs_t
*)ptr
;
3671 /* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
3672 if (CHIPID(sih
->chip
) == BCM43236_CHIP_ID
||
3673 CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) {
3674 regval
= R_REG(sii
->osh
, &cc
->chipcontrol
);
3676 W_REG(sii
->osh
, &cc
->chipcontrol
, regval
);
3678 regval
= R_REG(sii
->osh
, &cc
->jtagctrl
);
3680 W_REG(sii
->osh
, &cc
->jtagctrl
, regval
);
3683 /* enable SECI clock */
3684 si_seci_clkreq(sih
, TRUE
);
3686 /* put the SECI in reset */
3687 seci_conf
= R_REG(sii
->osh
, &cc
->SECI_config
);
3688 seci_conf
&= ~SECI_ENAB_SECI_ECI
;
3689 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3690 seci_conf
= SECI_RESET
;
3691 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3693 /* set force-low, and set EN_SECI for all non-legacy modes */
3694 seci_conf
|= SECI_ENAB_SECIOUT_DIS
;
3695 if ((seci_mode
== SECI_MODE_UART
) || (seci_mode
== SECI_MODE_SECI
) ||
3696 (seci_mode
== SECI_MODE_HALF_SECI
))
3698 seci_conf
|= SECI_ENAB_SECI_ECI
;
3700 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3702 /* take seci out of reset */
3703 seci_conf
= R_REG(sii
->osh
, &cc
->SECI_config
);
3704 seci_conf
&= ~(SECI_RESET
);
3705 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3707 /* set UART/SECI baud rate */
3708 /* hard-coded at 4MBaud for now */
3709 if ((seci_mode
== SECI_MODE_UART
) || (seci_mode
== SECI_MODE_SECI
) ||
3710 (seci_mode
== SECI_MODE_HALF_SECI
)) {
3711 offset
= OFFSETOF(chipcregs_t
, seci_uart_bauddiv
);
3712 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFF, 0xFF); /* 4MBaud */
3713 offset
= OFFSETOF(chipcregs_t
, seci_uart_baudadj
);
3714 if (CHIPID(sih
->chip
) == BCM43236_CHIP_ID
||
3715 CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) {
3716 /* 43236 ccrev = 36 and MAC clk = 96MHz */
3717 /* 4331 MAC clk = 96MHz */
3718 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFF, 0x44);
3721 /* 4336 MAC clk is 80MHz */
3722 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFF, 0x22);
3725 /* LCR/MCR settings */
3726 offset
= OFFSETOF(chipcregs_t
, seci_uart_lcr
);
3727 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFF,
3728 (SECI_UART_LCR_RX_EN
| SECI_UART_LCR_TXO_EN
)); /* 0x28 */
3729 offset
= OFFSETOF(chipcregs_t
, seci_uart_mcr
);
3730 si_corereg(sih
, SI_CC_IDX
, offset
,
3731 0xFF, (SECI_UART_MCR_TX_EN
| SECI_UART_MCR_BAUD_ADJ_EN
)); /* 0x81 */
3733 /* Give control of ECI output regs to MAC core */
3734 offset
= OFFSETOF(chipcregs_t
, eci
.ge35
.eci_controllo
);
3735 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFFFFFFFF, ECI_MACCTRLLO_BITS
);
3736 offset
= OFFSETOF(chipcregs_t
, eci
.ge35
.eci_controlhi
);
3737 si_corereg(sih
, SI_CC_IDX
, offset
, 0xFFFF, ECI_MACCTRLHI_BITS
);
3740 /* set the seci mode in seci conf register */
3741 seci_conf
= R_REG(sii
->osh
, &cc
->SECI_config
);
3742 seci_conf
&= ~(SECI_MODE_MASK
<< SECI_MODE_SHIFT
);
3743 seci_conf
|= (seci_mode
<< SECI_MODE_SHIFT
);
3744 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3746 /* Clear force-low bit */
3747 seci_conf
= R_REG(sii
->osh
, &cc
->SECI_config
);
3748 seci_conf
&= ~SECI_ENAB_SECIOUT_DIS
;
3749 W_REG(sii
->osh
, &cc
->SECI_config
, seci_conf
);
3751 /* restore previous core */
3753 si_setcoreidx(sih
, origidx
);
3757 #endif /* BCMECICOEX */
3760 si_btcgpiowar(si_t
*sih
)
3769 /* Make sure that there is ChipCommon core present &&
3770 * UART_TX is strapped to 1
3772 if (!(sih
->cccaps
& CC_CAP_UARTGPIO
))
3775 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
3776 INTR_OFF(sii
, intr_val
);
3778 origidx
= si_coreidx(sih
);
3780 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3783 W_REG(sii
->osh
, &cc
->uart0mcr
, R_REG(sii
->osh
, &cc
->uart0mcr
) | 0x04);
3785 /* restore the original index */
3786 si_setcoreidx(sih
, origidx
);
3788 INTR_RESTORE(sii
, intr_val
);
3791 #if !defined(_CFE_) || defined(CFG_WL)
3793 si_chipcontrl_epa4331_restore(si_t
*sih
, uint32 val
)
3800 origidx
= si_coreidx(sih
);
3801 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3802 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
3803 si_setcoreidx(sih
, origidx
);
3807 si_chipcontrl_epa4331_read(si_t
*sih
)
3815 origidx
= si_coreidx(sih
);
3816 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3817 val
= R_REG(sii
->osh
, &cc
->chipcontrol
);
3818 si_setcoreidx(sih
, origidx
);
3823 si_chipcontrl_epa4331(si_t
*sih
, bool on
)
3831 origidx
= si_coreidx(sih
);
3833 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3835 val
= R_REG(sii
->osh
, &cc
->chipcontrol
);
3838 if (sih
->chippkg
== 9 || sih
->chippkg
== 0xb) {
3839 val
|= (CCTRL4331_EXTPA_EN
| CCTRL4331_EXTPA_ON_GPIO2_5
);
3840 /* Ext PA Controls for 4331 12x9 Package */
3841 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
3843 /* Ext PA Controls for 4331 12x12 Package */
3844 if (sih
->chiprev
> 0) {
3845 W_REG(sii
->osh
, &cc
->chipcontrol
, val
|
3846 (CCTRL4331_EXTPA_EN
) | (CCTRL4331_EXTPA_EN2
));
3848 W_REG(sii
->osh
, &cc
->chipcontrol
, val
| (CCTRL4331_EXTPA_EN
));
3852 val
&= ~(CCTRL4331_EXTPA_EN
| CCTRL4331_EXTPA_EN2
| CCTRL4331_EXTPA_ON_GPIO2_5
);
3853 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
3856 si_setcoreidx(sih
, origidx
);
3860 si_chipcontrl_epa4331_wowl(si_t
*sih
, bool enter_wowl
)
3868 sel_chip
= (CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) ||
3869 (CHIPID(sih
->chip
) == BCM43431_CHIP_ID
);
3870 sel_chip
&= ((sih
->chippkg
== 9 || sih
->chippkg
== 0xb));
3876 origidx
= si_coreidx(sih
);
3878 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3880 val
= R_REG(sii
->osh
, &cc
->chipcontrol
);
3883 val
|= CCTRL4331_EXTPA_EN
;
3884 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
3886 val
|= (CCTRL4331_EXTPA_EN
| CCTRL4331_EXTPA_ON_GPIO2_5
);
3887 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
3889 si_setcoreidx(sih
, origidx
);
3891 #endif /* !_CFE_ || CFG_WL */
3894 si_pll_reset(si_t
*sih
)
3901 INTR_OFF(sii
, intr_val
);
3902 err
= si_pll_minresmask_reset(sih
, sii
->osh
);
3903 INTR_RESTORE(sii
, intr_val
);
3907 /* Enable BT-COEX & Ex-PA for 4313 */
3909 si_epa_4313war(si_t
*sih
)
3916 origidx
= si_coreidx(sih
);
3918 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3921 W_REG(sii
->osh
, &cc
->gpiocontrol
,
3922 R_REG(sii
->osh
, &cc
->gpiocontrol
) | GPIO_CTRL_EPA_EN_MASK
);
3924 si_setcoreidx(sih
, origidx
);
3928 si_clk_pmu_htavail_set(si_t
*sih
, bool set_clear
)
3933 si_pmu_minresmask_htavail_set(sih
, sii
->osh
, set_clear
);
3936 /* WL/BT control for 4313 btcombo boards >= P250 */
3938 si_btcombo_p250_4313_war(si_t
*sih
)
3945 origidx
= si_coreidx(sih
);
3947 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3948 W_REG(sii
->osh
, &cc
->gpiocontrol
,
3949 R_REG(sii
->osh
, &cc
->gpiocontrol
) | GPIO_CTRL_5_6_EN_MASK
);
3951 W_REG(sii
->osh
, &cc
->gpioouten
,
3952 R_REG(sii
->osh
, &cc
->gpioouten
) | GPIO_CTRL_5_6_EN_MASK
);
3954 si_setcoreidx(sih
, origidx
);
3957 si_btc_enable_chipcontrol(si_t
*sih
)
3964 origidx
= si_coreidx(sih
);
3966 cc
= (chipcregs_t
*)si_setcore(sih
, CC_CORE_ID
, 0);
3969 W_REG(sii
->osh
, &cc
->chipcontrol
,
3970 R_REG(sii
->osh
, &cc
->chipcontrol
) | CC_BTCOEX_EN_MASK
);
3972 si_setcoreidx(sih
, origidx
);
3974 /* check if the device is removed */
3976 si_deviceremoved(si_t
*sih
)
3983 switch (BUSTYPE(sih
->bustype
)) {
3985 ASSERT(sii
->osh
!= NULL
);
3986 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_VID
, sizeof(uint32
));
3987 if ((w
& 0xFFFF) != VENDOR_BROADCOM
)
3995 si_is_sprom_available(si_t
*sih
)
3997 if (sih
->ccrev
>= 31) {
4003 if ((sih
->cccaps
& CC_CAP_SROM
) == 0)
4007 origidx
= sii
->curidx
;
4008 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
4009 sromctrl
= R_REG(sii
->osh
, &cc
->sromcontrol
);
4010 si_setcoreidx(sih
, origidx
);
4011 return (sromctrl
& SRC_PRESENT
);
4014 switch (CHIPID(sih
->chip
)) {
4015 case BCM4312_CHIP_ID
:
4016 return ((sih
->chipst
& CST4312_SPROM_OTP_SEL_MASK
) != CST4312_OTP_SEL
);
4017 case BCM4325_CHIP_ID
:
4018 return (sih
->chipst
& CST4325_SPROM_SEL
) != 0;
4019 case BCM4322_CHIP_ID
: case BCM43221_CHIP_ID
: case BCM43231_CHIP_ID
:
4020 case BCM43222_CHIP_ID
: case BCM43111_CHIP_ID
: case BCM43112_CHIP_ID
:
4021 case BCM43420_CHIP_ID
:
4022 case BCM4342_CHIP_ID
: {
4024 spromotp
= (sih
->chipst
& CST4322_SPROM_OTP_SEL_MASK
) >>
4025 CST4322_SPROM_OTP_SEL_SHIFT
;
4026 return (spromotp
& CST4322_SPROM_PRESENT
) != 0;
4028 case BCM4329_CHIP_ID
:
4029 return (sih
->chipst
& CST4329_SPROM_SEL
) != 0;
4030 case BCM4315_CHIP_ID
:
4031 return (sih
->chipst
& CST4315_SPROM_SEL
) != 0;
4032 case BCM4319_CHIP_ID
:
4033 return (sih
->chipst
& CST4319_SPROM_SEL
) != 0;
4034 case BCM4336_CHIP_ID
:
4035 return (sih
->chipst
& CST4336_SPROM_PRESENT
) != 0;
4036 case BCM4330_CHIP_ID
:
4037 return (sih
->chipst
& CST4330_SPROM_PRESENT
) != 0;
4038 case BCM4313_CHIP_ID
:
4039 return (sih
->chipst
& CST4313_SPROM_PRESENT
) != 0;
4040 case BCM4331_CHIP_ID
:
4041 case BCM43431_CHIP_ID
:
4042 return (sih
->chipst
& CST4331_SPROM_PRESENT
) != 0;
4043 case BCM43131_CHIP_ID
:
4044 case BCM43227_CHIP_ID
:
4045 case BCM43228_CHIP_ID
:
4046 case BCM43428_CHIP_ID
:
4047 return (sih
->chipst
& CST43228_OTP_PRESENT
) != CST43228_OTP_PRESENT
;
4054 si_is_otp_disabled(si_t
*sih
)
4056 switch (CHIPID(sih
->chip
)) {
4057 case BCM4325_CHIP_ID
:
4058 return (sih
->chipst
& CST4325_SPROM_OTP_SEL_MASK
) == CST4325_OTP_PWRDN
;
4059 case BCM4322_CHIP_ID
:
4060 case BCM43221_CHIP_ID
:
4061 case BCM43231_CHIP_ID
:
4062 case BCM4342_CHIP_ID
:
4063 return (((sih
->chipst
& CST4322_SPROM_OTP_SEL_MASK
) >>
4064 CST4322_SPROM_OTP_SEL_SHIFT
) & CST4322_OTP_PRESENT
) !=
4065 CST4322_OTP_PRESENT
;
4066 case BCM4329_CHIP_ID
:
4067 return (sih
->chipst
& CST4329_SPROM_OTP_SEL_MASK
) == CST4329_OTP_PWRDN
;
4068 case BCM4315_CHIP_ID
:
4069 return (sih
->chipst
& CST4315_SPROM_OTP_SEL_MASK
) == CST4315_OTP_PWRDN
;
4070 case BCM4319_CHIP_ID
:
4071 return (sih
->chipst
& CST4319_SPROM_OTP_SEL_MASK
) == CST4319_OTP_PWRDN
;
4072 case BCM4336_CHIP_ID
:
4073 return ((sih
->chipst
& CST4336_OTP_PRESENT
) == 0);
4074 case BCM4330_CHIP_ID
:
4075 return ((sih
->chipst
& CST4330_OTP_PRESENT
) == 0);
4076 case BCM4313_CHIP_ID
:
4077 return (sih
->chipst
& CST4313_OTP_PRESENT
) == 0;
4078 /* These chips always have their OTP on */
4079 case BCM43111_CHIP_ID
: case BCM43112_CHIP_ID
: case BCM43222_CHIP_ID
:
4080 case BCM43224_CHIP_ID
: case BCM43225_CHIP_ID
: case BCM43420_CHIP_ID
:
4081 case BCM43421_CHIP_ID
:
4082 case BCM43226_CHIP_ID
:
4083 case BCM43235_CHIP_ID
: case BCM43236_CHIP_ID
: case BCM43238_CHIP_ID
:
4084 case BCM43234_CHIP_ID
: case BCM43237_CHIP_ID
:
4085 case BCM4331_CHIP_ID
: case BCM43431_CHIP_ID
:
4086 case BCM43131_CHIP_ID
:
4087 case BCM43227_CHIP_ID
:
4088 case BCM43228_CHIP_ID
: case BCM43428_CHIP_ID
:
4095 si_is_otp_powered(si_t
*sih
)
4097 if (PMUCTL_ENAB(sih
))
4098 return si_pmu_is_otp_powered(sih
, si_osh(sih
));
4103 si_otp_power(si_t
*sih
, bool on
)
4105 if (PMUCTL_ENAB(sih
))
4106 si_pmu_otp_power(sih
, si_osh(sih
), on
);
4111 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4112 si_is_sprom_enabled(si_t
*sih
)
4114 BCMATTACHFN(si_is_sprom_enabled
)(si_t
*sih
)
4117 if (PMUCTL_ENAB(sih
))
4118 return si_pmu_is_sprom_enabled(sih
, si_osh(sih
));
4123 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
4124 si_sprom_enable(si_t
*sih
, bool enable
)
4126 BCMATTACHFN(si_sprom_enable
)(si_t
*sih
, bool enable
)
4129 if (PMUCTL_ENAB(sih
))
4130 si_pmu_sprom_enable(sih
, si_osh(sih
), enable
);
4133 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
4135 si_cis_source(si_t
*sih
)
4137 /* Many chips have the same mapping of their chipstatus field */
4138 static const uint cis_sel
[] = { CIS_DEFAULT
, CIS_SROM
, CIS_OTP
, CIS_SROM
};
4139 static const uint cis_sel_1b
[] = { CIS_DEFAULT
, CIS_OTP
};
4140 UNUSED_PARAMETER(cis_sel_1b
);
4142 /* PCI chips use SROM format instead of CIS */
4143 if (BUSTYPE(sih
->bustype
) == PCI_BUS
)
4144 return BCME_NOTFOUND
;
4146 switch (CHIPID(sih
->chip
)) {
4147 case BCM4325_CHIP_ID
:
4148 return ((sih
->chipst
& CST4325_SPROM_OTP_SEL_MASK
) >= sizeof(cis_sel
)) ?
4149 CIS_DEFAULT
: cis_sel
[(sih
->chipst
& CST4325_SPROM_OTP_SEL_MASK
)];
4150 case BCM4322_CHIP_ID
: case BCM43221_CHIP_ID
: case BCM43231_CHIP_ID
:
4151 case BCM4342_CHIP_ID
: {
4152 uint8 strap
= (sih
->chipst
& CST4322_SPROM_OTP_SEL_MASK
) >>
4153 CST4322_SPROM_OTP_SEL_SHIFT
;
4154 return ((strap
>= ARRAYSIZE(cis_sel
)) ? CIS_DEFAULT
: cis_sel
[strap
]);
4157 case BCM43235_CHIP_ID
: case BCM43236_CHIP_ID
: case BCM43238_CHIP_ID
:
4158 case BCM43234_CHIP_ID
: {
4159 uint8 strap
= (sih
->chipst
& CST43236_OTP_SEL_MASK
) >>
4160 CST43236_OTP_SEL_SHIFT
;
4161 UNUSED_PARAMETER(strap
);
4165 case BCM43237_CHIP_ID
: {
4166 uint8 strap
= (sih
->chipst
& CST43237_OTP_SEL_MASK
) >>
4167 CST43237_OTP_SEL_SHIFT
;
4168 return cis_sel_1b
[strap
];
4171 case BCM4329_CHIP_ID
:
4172 return ((sih
->chipst
& CST4329_SPROM_OTP_SEL_MASK
) >= sizeof(cis_sel
)) ?
4173 CIS_DEFAULT
: cis_sel
[(sih
->chipst
& CST4329_SPROM_OTP_SEL_MASK
)];
4174 case BCM4315_CHIP_ID
:
4175 return ((sih
->chipst
& CST4315_SPROM_OTP_SEL_MASK
) >= sizeof(cis_sel
)) ?
4176 CIS_DEFAULT
: cis_sel
[(sih
->chipst
& CST4315_SPROM_OTP_SEL_MASK
)];
4177 case BCM4319_CHIP_ID
: {
4178 uint cis_sel4319
= ((sih
->chipst
& CST4319_SPROM_OTP_SEL_MASK
) >>
4179 CST4319_SPROM_OTP_SEL_SHIFT
);
4180 return (cis_sel4319
>= ARRAYSIZE(cis_sel
)) ? CIS_DEFAULT
: cis_sel
[cis_sel4319
];
4182 case BCM4336_CHIP_ID
: {
4183 if (sih
->chipst
& CST4336_SPROM_PRESENT
)
4185 if (sih
->chipst
& CST4336_OTP_PRESENT
)
4189 case BCM4330_CHIP_ID
: {
4190 if (sih
->chipst
& CST4330_SPROM_PRESENT
)
4192 if (sih
->chipst
& CST4330_OTP_PRESENT
)
4201 /* Read/write to OTP to find the FAB manf */
4203 BCMINITFN(si_otp_fabid
)(si_t
*sih
, uint16
*fabid
, bool rw
)
4205 int error
= BCME_OK
;
4207 uint16 data
, mask
= 0, shift
= 0;
4209 switch (CHIPID(sih
->chip
)) {
4210 case BCM4329_CHIP_ID
:
4211 /* Bit locations 133-130 */
4212 if (sih
->chiprev
>= 3) {
4218 case BCM5356_CHIP_ID
:
4219 /* Bit locations 133-130 */
4231 error
= otp_read_word(sih
, offset
, &data
);
4233 *fabid
= (data
& mask
) >> shift
;
4236 data
= (data
<< shift
) & mask
;
4238 error
= otp_write_word(sih
, offset
, data
);
4239 #endif /* BCMNVRAMW */
4245 uint16
BCMINITFN(si_fabid
)(si_t
*sih
)
4248 if (si_otp_fabid(sih
, &fabid
, TRUE
) != BCME_OK
)
4250 SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));