2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <linux/kernel.h>
21 #include <linux/string.h>
29 #include <pcie_core.h>
41 #include <sbsdpcmdev.h>
46 /* this file now contains only definitions for sb functions, only necessary
47 *for devices using Sonics backplanes (bcm4329)
50 /* if an amba SDIO device is supported, please further restrict the inclusion
54 #include "siutils_priv.h"
57 /* local prototypes */
58 static si_info_t
*si_doattach(si_info_t
*sii
, uint devid
, osl_t
*osh
,
59 void *regs
, uint bustype
, void *sdh
, char **vars
,
61 static bool si_buscore_prep(si_info_t
*sii
, uint bustype
, uint devid
,
63 static bool si_buscore_setup(si_info_t
*sii
, chipcregs_t
*cc
, uint bustype
,
64 uint32 savewin
, uint
*origidx
, void *regs
);
65 static void si_nvram_process(si_info_t
*sii
, char *pvars
);
67 /* dev path concatenation util */
68 static char *si_devpathvar(si_t
*sih
, char *var
, int len
, const char *name
);
69 static bool _si_clkctl_cc(si_info_t
*sii
, uint mode
);
70 static bool si_ispcie(si_info_t
*sii
);
71 static uint
BCMINITFN(socram_banksize
) (si_info_t
*sii
, sbsocramregs_t
*r
,
74 /* global variable to indicate reservation/release of gpio's */
75 static uint32 si_gpioreservation
;
77 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
80 * Allocate a si handle.
81 * devid - pci device id (used to determine chip#)
82 * osh - opaque OS handle
83 * regs - virtual address of initial core registers
84 * bustype - pci/sb/sdio/etc
85 * vars - pointer to a pointer area for "environment" variables
86 * varsz - pointer to int to return the size of the vars
88 si_t
*BCMATTACHFN(si_attach
) (uint devid
, osl_t
*osh
, void *regs
,
89 uint bustype
, void *sdh
, char **vars
,
94 sii
= MALLOC(osh
, sizeof(si_info_t
));
96 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n",
101 if (si_doattach(sii
, devid
, osh
, regs
, bustype
, sdh
, vars
, varsz
) ==
103 MFREE(osh
, sii
, sizeof(si_info_t
));
106 sii
->vars
= vars
? *vars
: NULL
;
107 sii
->varsz
= varsz
? *varsz
: 0;
112 /* global kernel resource */
113 static si_info_t ksii
;
115 static uint32 wd_msticks
; /* watchdog timer ticks normalized to ms */
118 BCMATTACHFN(si_buscore_prep
) (si_info_t
*sii
, uint bustype
, uint devid
,
122 /* kludge to enable the clock on the 4306 which lacks a slowclock */
123 if (BUSTYPE(bustype
) == PCI_BUS
&& !si_ispcie(sii
))
124 si_clkctl_xtal(&sii
->pub
, XTAL
| PLL
, ON
);
128 if (BUSTYPE(bustype
) == SDIO_BUS
) {
132 /* Try forcing SDIO core to do ALPAvail request only */
133 clkset
= SBSDIO_FORCE_HW_CLKREQ_OFF
| SBSDIO_ALP_AVAIL_REQ
;
134 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_CHIPCLKCSR
,
139 /* If register supported, wait for ALPAvail and then force ALP */
141 bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
142 SBSDIO_FUNC1_CHIPCLKCSR
, NULL
);
143 if ((clkval
& ~SBSDIO_AVBITS
) == clkset
) {
145 bcmsdh_cfg_read(sdh
, SDIO_FUNC_1
,
146 SBSDIO_FUNC1_CHIPCLKCSR
,
148 !SBSDIO_ALPAV(clkval
)),
149 PMU_MAX_TRANSITION_DLY
);
150 if (!SBSDIO_ALPAV(clkval
)) {
151 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval
));
155 SBSDIO_FORCE_HW_CLKREQ_OFF
|
157 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
,
158 SBSDIO_FUNC1_CHIPCLKCSR
,
164 /* Also, disable the extra SDIO pull-ups */
165 bcmsdh_cfg_write(sdh
, SDIO_FUNC_1
, SBSDIO_FUNC1_SDIOPULLUP
, 0,
168 #endif /* defined(BCMSDIO) */
174 BCMATTACHFN(si_buscore_setup
) (si_info_t
*sii
, chipcregs_t
*cc
, uint bustype
,
175 uint32 savewin
, uint
*origidx
, void *regs
) {
178 uint pciidx
, pcieidx
, pcirev
, pcierev
;
180 cc
= si_setcoreidx(&sii
->pub
, SI_CC_IDX
);
181 ASSERT((uintptr
) cc
);
183 /* get chipcommon rev */
184 sii
->pub
.ccrev
= (int)si_corerev(&sii
->pub
);
186 /* get chipcommon chipstatus */
187 if (sii
->pub
.ccrev
>= 11)
188 sii
->pub
.chipst
= R_REG(sii
->osh
, &cc
->chipstatus
);
190 /* get chipcommon capabilites */
191 sii
->pub
.cccaps
= R_REG(sii
->osh
, &cc
->capabilities
);
192 /* get chipcommon extended capabilities */
195 if (sii
->pub
.ccrev
>= 35)
196 sii
->pub
.cccaps_ext
= R_REG(sii
->osh
, &cc
->capabilities_ext
);
198 /* get pmu rev and caps */
199 if (sii
->pub
.cccaps
& CC_CAP_PMU
) {
200 sii
->pub
.pmucaps
= R_REG(sii
->osh
, &cc
->pmucapabilities
);
201 sii
->pub
.pmurev
= sii
->pub
.pmucaps
& PCAP_REV_MASK
;
205 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
206 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
210 /* figure out bus/orignal core idx */
211 sii
->pub
.buscoretype
= NODEV_CORE_ID
;
212 sii
->pub
.buscorerev
= NOREV
;
213 sii
->pub
.buscoreidx
= BADIDX
;
216 pcirev
= pcierev
= NOREV
;
217 pciidx
= pcieidx
= BADIDX
;
219 for (i
= 0; i
< sii
->numcores
; i
++) {
222 si_setcoreidx(&sii
->pub
, i
);
223 cid
= si_coreid(&sii
->pub
);
224 crev
= si_corerev(&sii
->pub
);
226 /* Display cores found */
227 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
228 i
, cid
, crev
, sii
->coresba
[i
], sii
->regs
[i
]));
230 if (BUSTYPE(bustype
) == PCI_BUS
) {
231 if (cid
== PCI_CORE_ID
) {
235 } else if (cid
== PCIE_CORE_ID
) {
242 else if (((BUSTYPE(bustype
) == SDIO_BUS
) ||
243 (BUSTYPE(bustype
) == SPI_BUS
)) &&
244 ((cid
== PCMCIA_CORE_ID
) || (cid
== SDIOD_CORE_ID
))) {
245 sii
->pub
.buscorerev
= crev
;
246 sii
->pub
.buscoretype
= cid
;
247 sii
->pub
.buscoreidx
= i
;
251 /* find the core idx before entering this func. */
252 if ((savewin
&& (savewin
== sii
->coresba
[i
])) ||
253 (regs
== sii
->regs
[i
]))
258 SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii
->pub
.buscoreidx
,
259 sii
->pub
.buscoretype
, sii
->pub
.buscorerev
));
261 /* Make sure any on-chip ARM is off (in case strapping is wrong),
262 * or downloaded code was
265 if ((BUSTYPE(bustype
) == SDIO_BUS
) || (BUSTYPE(bustype
) == SPI_BUS
)) {
266 if (si_setcore(&sii
->pub
, ARM7S_CORE_ID
, 0) ||
267 si_setcore(&sii
->pub
, ARMCM3_CORE_ID
, 0))
268 si_core_disable(&sii
->pub
, 0);
278 sii
->pub
.buscoretype
= PCI_CORE_ID
;
279 sii
->pub
.buscorerev
= pcirev
;
280 sii
->pub
.buscoreidx
= pciidx
;
282 sii
->pub
.buscoretype
= PCIE_CORE_ID
;
283 sii
->pub
.buscorerev
= pcierev
;
284 sii
->pub
.buscoreidx
= pcieidx
;
287 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii
->pub
.buscoreidx
,
288 sii
->pub
.buscoretype
, sii
->pub
.buscorerev
));
290 /* fixup necessary chip/core configurations */
291 if (BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
) {
294 sii
->pch
= (void *)(uintptr
)pcicore_init(
296 (void *)PCIEREGS(sii
));
297 if (sii
->pch
== NULL
)
301 if (si_pci_fixcfg(&sii
->pub
)) {
302 SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
307 /* return to the original core */
308 si_setcoreidx(&sii
->pub
, *origidx
);
313 static __used
void BCMATTACHFN(si_nvram_process
) (si_info_t
*sii
, char *pvars
)
317 /* get boardtype and boardrev */
318 switch (BUSTYPE(sii
->pub
.bustype
)) {
320 /* do a pci config read to get subsystem id and subvendor id */
321 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_SVID
, sizeof(uint32
));
322 /* Let nvram variables override subsystem Vend/ID */
323 sii
->pub
.boardvendor
= (uint16
)si_getdevpathintvar(&sii
->pub
,
325 if (sii
->pub
.boardvendor
== 0)
326 sii
->pub
.boardvendor
= w
& 0xffff;
328 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii
->pub
.boardvendor
, w
& 0xffff));
329 sii
->pub
.boardtype
= (uint16
)si_getdevpathintvar(&sii
->pub
,
331 if (sii
->pub
.boardtype
== 0)
332 sii
->pub
.boardtype
= (w
>> 16) & 0xffff;
334 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii
->pub
.boardtype
, (w
>> 16) & 0xffff));
340 sii
->pub
.boardvendor
= getintvar(pvars
, "manfid");
341 sii
->pub
.boardtype
= getintvar(pvars
, "prodid");
346 sii
->pub
.boardvendor
= VENDOR_BROADCOM
;
347 sii
->pub
.boardtype
= SPI_BOARD
;
353 sii
->pub
.boardvendor
= VENDOR_BROADCOM
;
354 sii
->pub
.boardtype
= getintvar(pvars
, "prodid");
355 if (pvars
== NULL
|| (sii
->pub
.boardtype
== 0)) {
356 sii
->pub
.boardtype
= getintvar(NULL
, "boardtype");
357 if (sii
->pub
.boardtype
== 0)
358 sii
->pub
.boardtype
= 0xffff;
363 if (sii
->pub
.boardtype
== 0) {
364 SI_ERROR(("si_doattach: unknown board type\n"));
365 ASSERT(sii
->pub
.boardtype
);
368 sii
->pub
.boardflags
= getintvar(pvars
, "boardflags");
371 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
372 /* this has been customized for the bcm 4329 ONLY */
374 static si_info_t
*BCMATTACHFN(si_doattach
) (si_info_t
*sii
, uint devid
,
375 osl_t
*osh
, void *regs
,
376 uint bustype
, void *sdh
,
377 char **vars
, uint
*varsz
) {
378 struct si_pub
*sih
= &sii
->pub
;
384 ASSERT(GOODREGS(regs
));
386 bzero((unsigned char *) sii
, sizeof(si_info_t
));
390 sih
->buscoreidx
= BADIDX
;
396 /* find Chipcommon address */
397 cc
= (chipcregs_t
*) sii
->curmap
;
398 sih
->bustype
= bustype
;
400 if (bustype
!= BUSTYPE(bustype
)) {
401 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype
, BUSTYPE(bustype
)));
405 /* bus/core/clk setup for register access */
406 if (!si_buscore_prep(sii
, bustype
, devid
, sdh
)) {
407 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
412 /* ChipID recognition.
413 * We assume we can read chipid at offset 0 from the regs arg.
414 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
415 * some way of recognizing them needs to be added here.
417 w
= R_REG(osh
, &cc
->chipid
);
418 sih
->socitype
= (w
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
419 /* Might as wll fill in chip id rev & pkg */
420 sih
->chip
= w
& CID_ID_MASK
;
421 sih
->chiprev
= (w
& CID_REV_MASK
) >> CID_REV_SHIFT
;
422 sih
->chippkg
= (w
& CID_PKG_MASK
) >> CID_PKG_SHIFT
;
424 if ((CHIPID(sih
->chip
) == BCM4329_CHIP_ID
) &&
425 (sih
->chippkg
!= BCM4329_289PIN_PKG_ID
))
426 sih
->chippkg
= BCM4329_182PIN_PKG_ID
;
428 sih
->issim
= IS_SIM(sih
->chippkg
);
431 /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
432 sb_scan(&sii
->pub
, regs
, devid
);
434 /* no cores found, bail out */
435 if (sii
->numcores
== 0) {
436 SI_ERROR(("si_doattach: could not find any cores\n"));
439 /* bus/core/clk setup */
441 if (!si_buscore_setup(sii
, cc
, bustype
, savewin
, &origidx
, regs
)) {
442 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
449 /* Init nvram from flash if it exists */
450 nvram_init((void *)&(sii
->pub
));
452 /* Init nvram from sprom/otp if they exist */
454 (&sii
->pub
, BUSTYPE(bustype
), regs
, sii
->osh
, vars
, varsz
)) {
455 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
458 pvars
= vars
? *vars
: NULL
;
459 si_nvram_process(sii
, pvars
);
462 /* === NVRAM, clock is ready === */
465 if (sii
->pub
.ccrev
>= 20) {
467 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
468 W_REG(osh
, &cc
->gpiopullup
, 0);
469 W_REG(osh
, &cc
->gpiopulldown
, 0);
470 sb_setcoreidx(sih
, origidx
);
476 /* PMU specific initializations */
477 if (PMUCTL_ENAB(sih
)) {
479 si_pmu_init(sih
, sii
->osh
);
480 si_pmu_chip_init(sih
, sii
->osh
);
481 xtalfreq
= getintvar(pvars
, "xtalfreq");
482 /* If xtalfreq var not available, try to measure it */
484 xtalfreq
= si_pmu_measure_alpclk(sih
, sii
->osh
);
485 si_pmu_pll_init(sih
, sii
->osh
, xtalfreq
);
486 si_pmu_res_init(sih
, sii
->osh
);
487 si_pmu_swreg_init(sih
, sii
->osh
);
490 /* setup the GPIO based LED powersave register */
491 w
= getintvar(pvars
, "leddc");
493 w
= DEFAULT_GPIOTIMERVAL
;
494 sb_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, gpiotimerval
), ~0, w
);
497 /* clear any previous epidiag-induced target abort */
498 sb_taclear(sih
, FALSE
);
509 static si_info_t
*BCMATTACHFN(si_doattach
) (si_info_t
*sii
, uint devid
,
510 osl_t
*osh
, void *regs
,
511 uint bustype
, void *sdh
,
512 char **vars
, uint
*varsz
) {
513 struct si_pub
*sih
= &sii
->pub
;
519 ASSERT(GOODREGS(regs
));
521 bzero((unsigned char *) sii
, sizeof(si_info_t
));
525 sih
->buscoreidx
= BADIDX
;
531 /* check to see if we are a si core mimic'ing a pci core */
532 if ((bustype
== PCI_BUS
) &&
533 (OSL_PCI_READ_CONFIG(sii
->osh
, PCI_SPROM_CONTROL
, sizeof(uint32
)) ==
535 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " "devid:0x%x\n", __func__
, devid
));
539 /* find Chipcommon address */
540 if (bustype
== PCI_BUS
) {
542 OSL_PCI_READ_CONFIG(sii
->osh
, PCI_BAR0_WIN
, sizeof(uint32
));
543 if (!GOODCOREADDR(savewin
, SI_ENUM_BASE
))
544 savewin
= SI_ENUM_BASE
;
545 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_BAR0_WIN
, 4, SI_ENUM_BASE
);
546 cc
= (chipcregs_t
*) regs
;
548 cc
= (chipcregs_t
*) REG_MAP(SI_ENUM_BASE
, SI_CORE_SIZE
);
551 sih
->bustype
= bustype
;
552 if (bustype
!= BUSTYPE(bustype
)) {
553 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype
, BUSTYPE(bustype
)));
557 /* bus/core/clk setup for register access */
558 if (!si_buscore_prep(sii
, bustype
, devid
, sdh
)) {
559 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
564 /* ChipID recognition.
565 * We assume we can read chipid at offset 0 from the regs arg.
566 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
567 * some way of recognizing them needs to be added here.
569 w
= R_REG(osh
, &cc
->chipid
);
570 sih
->socitype
= (w
& CID_TYPE_MASK
) >> CID_TYPE_SHIFT
;
571 /* Might as wll fill in chip id rev & pkg */
572 sih
->chip
= w
& CID_ID_MASK
;
573 sih
->chiprev
= (w
& CID_REV_MASK
) >> CID_REV_SHIFT
;
574 sih
->chippkg
= (w
& CID_PKG_MASK
) >> CID_PKG_SHIFT
;
576 sih
->issim
= IS_SIM(sih
->chippkg
);
579 if (CHIPTYPE(sii
->pub
.socitype
) == SOCI_AI
) {
580 SI_MSG(("Found chip type AI (0x%08x)\n", w
));
581 /* pass chipc address instead of original core base */
582 ai_scan(&sii
->pub
, (void *)(uintptr
) cc
, devid
);
584 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w
));
587 /* no cores found, bail out */
588 if (sii
->numcores
== 0) {
589 SI_ERROR(("si_doattach: could not find any cores\n"));
592 /* bus/core/clk setup */
594 if (!si_buscore_setup(sii
, cc
, bustype
, savewin
, &origidx
, regs
)) {
595 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
599 /* assume current core is CC */
600 if ((sii
->pub
.ccrev
== 0x25)
602 ((CHIPID(sih
->chip
) == BCM43236_CHIP_ID
603 || CHIPID(sih
->chip
) == BCM43235_CHIP_ID
604 || CHIPID(sih
->chip
) == BCM43238_CHIP_ID
)
605 && (CHIPREV(sii
->pub
.chiprev
) <= 2))) {
607 if ((cc
->chipstatus
& CST43236_BP_CLK
) != 0) {
609 clkdiv
= R_REG(osh
, &cc
->clkdiv
);
610 /* otp_clk_div is even number, 120/14 < 9mhz */
611 clkdiv
= (clkdiv
& ~CLKD_OTP
) | (14 << CLKD_OTP_SHIFT
);
612 W_REG(osh
, &cc
->clkdiv
, clkdiv
);
613 SI_ERROR(("%s: set clkdiv to %x\n", __func__
, clkdiv
));
618 /* Init nvram from flash if it exists */
619 nvram_init((void *)&(sii
->pub
));
621 /* Init nvram from sprom/otp if they exist */
623 (&sii
->pub
, BUSTYPE(bustype
), regs
, sii
->osh
, vars
, varsz
)) {
624 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
627 pvars
= vars
? *vars
: NULL
;
628 si_nvram_process(sii
, pvars
);
630 /* === NVRAM, clock is ready === */
631 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
632 W_REG(osh
, &cc
->gpiopullup
, 0);
633 W_REG(osh
, &cc
->gpiopulldown
, 0);
634 si_setcoreidx(sih
, origidx
);
636 /* PMU specific initializations */
637 if (PMUCTL_ENAB(sih
)) {
639 si_pmu_init(sih
, sii
->osh
);
640 si_pmu_chip_init(sih
, sii
->osh
);
641 xtalfreq
= getintvar(pvars
, "xtalfreq");
642 /* If xtalfreq var not available, try to measure it */
644 xtalfreq
= si_pmu_measure_alpclk(sih
, sii
->osh
);
645 si_pmu_pll_init(sih
, sii
->osh
, xtalfreq
);
646 si_pmu_res_init(sih
, sii
->osh
);
647 si_pmu_swreg_init(sih
, sii
->osh
);
650 /* setup the GPIO based LED powersave register */
651 w
= getintvar(pvars
, "leddc");
653 w
= DEFAULT_GPIOTIMERVAL
;
654 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, gpiotimerval
), ~0, w
);
657 ASSERT(sii
->pch
!= NULL
);
658 pcicore_attach(sii
->pch
, pvars
, SI_DOATTACH
);
661 if ((CHIPID(sih
->chip
) == BCM43224_CHIP_ID
) ||
662 (CHIPID(sih
->chip
) == BCM43421_CHIP_ID
)) {
663 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
664 if (CHIPREV(sih
->chiprev
) == 0) {
665 SI_MSG(("Applying 43224A0 WARs\n"));
666 si_corereg(sih
, SI_CC_IDX
,
667 OFFSETOF(chipcregs_t
, chipcontrol
),
668 CCTRL43224_GPIO_TOGGLE
,
669 CCTRL43224_GPIO_TOGGLE
);
670 si_pmu_chipcontrol(sih
, 0, CCTRL_43224A0_12MA_LED_DRIVE
,
671 CCTRL_43224A0_12MA_LED_DRIVE
);
673 if (CHIPREV(sih
->chiprev
) >= 1) {
674 SI_MSG(("Applying 43224B0+ WARs\n"));
675 si_pmu_chipcontrol(sih
, 0, CCTRL_43224B0_12MA_LED_DRIVE
,
676 CCTRL_43224B0_12MA_LED_DRIVE
);
680 if (CHIPID(sih
->chip
) == BCM4313_CHIP_ID
) {
681 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
682 SI_MSG(("Applying 4313 WARs\n"));
683 si_pmu_chipcontrol(sih
, 0, CCTRL_4313_12MA_LED_DRIVE
,
684 CCTRL_4313_12MA_LED_DRIVE
);
687 if (CHIPID(sih
->chip
) == BCM4331_CHIP_ID
) {
688 /* Enable Ext PA lines depending on chip package option */
689 si_chipcontrl_epa4331(sih
, TRUE
);
694 if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
696 pcicore_deinit(sii
->pch
);
704 /* may be called with core in reset */
705 void BCMATTACHFN(si_detach
) (si_t
*sih
)
710 struct si_pub
*si_local
= NULL
;
711 bcopy(&sih
, &si_local
, sizeof(si_t
**));
718 if (BUSTYPE(sih
->bustype
) == SI_BUS
)
719 for (idx
= 0; idx
< SI_MAXCORES
; idx
++)
720 if (sii
->regs
[idx
]) {
721 REG_UNMAP(sii
->regs
[idx
]);
722 sii
->regs
[idx
] = NULL
;
726 nvram_exit((void *)si_local
); /* free up nvram buffers */
728 if (BUSTYPE(sih
->bustype
) == PCI_BUS
) {
730 pcicore_deinit(sii
->pch
);
734 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
736 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
737 MFREE(sii
->osh
, sii
, sizeof(si_info_t
));
740 void *si_osh(si_t
*sih
)
748 void si_setosh(si_t
*sih
, osl_t
*osh
)
753 if (sii
->osh
!= NULL
) {
754 SI_ERROR(("osh is already set....\n"));
760 /* register driver interrupt disabling and restoring callback functions */
762 si_register_intr_callback(si_t
*sih
, void *intrsoff_fn
, void *intrsrestore_fn
,
763 void *intrsenabled_fn
, void *intr_arg
)
768 sii
->intr_arg
= intr_arg
;
769 sii
->intrsoff_fn
= (si_intrsoff_t
) intrsoff_fn
;
770 sii
->intrsrestore_fn
= (si_intrsrestore_t
) intrsrestore_fn
;
771 sii
->intrsenabled_fn
= (si_intrsenabled_t
) intrsenabled_fn
;
772 /* save current core id. when this function called, the current core
773 * must be the core which provides driver functions(il, et, wl, etc.)
775 sii
->dev_coreid
= sii
->coreid
[sii
->curidx
];
778 void si_deregister_intr_callback(si_t
*sih
)
783 sii
->intrsoff_fn
= NULL
;
786 uint
si_intflag(si_t
*sih
)
788 si_info_t
*sii
= SI_INFO(sih
);
790 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
791 return R_REG(sii
->osh
,
792 ((uint32
*) (uintptr
) (sii
->oob_router
+
800 uint
si_flag(si_t
*sih
)
802 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
810 void si_setint(si_t
*sih
, int siflag
)
812 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
813 ai_setint(sih
, siflag
);
819 uint
si_coreid(si_t
*sih
)
824 return sii
->coreid
[sii
->curidx
];
828 uint
si_coreidx(si_t
*sih
)
836 /* return the core-type instantiation # of the current core */
837 uint
si_coreunit(si_t
*sih
)
850 ASSERT(GOODREGS(sii
->curmap
));
851 coreid
= si_coreid(sih
);
853 /* count the cores of our type */
854 for (i
= 0; i
< idx
; i
++)
855 if (sii
->coreid
[i
] == coreid
)
861 uint
si_corevendor(si_t
*sih
)
863 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
864 return ai_corevendor(sih
);
871 bool si_backplane64(si_t
*sih
)
873 return (sih
->cccaps
& CC_CAP_BKPLN64
) != 0;
877 uint
si_corerev(si_t
*sih
)
879 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
880 return ai_corerev(sih
);
888 /* return index of coreid or BADIDX if not found */
889 uint
si_findcoreidx(si_t
*sih
, uint coreid
, uint coreunit
)
899 for (i
= 0; i
< sii
->numcores
; i
++)
900 if (sii
->coreid
[i
] == coreid
) {
901 if (found
== coreunit
)
909 /* return list of found cores */
910 uint
si_corelist(si_t
*sih
, uint coreid
[])
916 bcopy((unsigned char *) sii
->coreid
, (unsigned char *) coreid
,
917 (sii
->numcores
* sizeof(uint
)));
918 return sii
->numcores
;
921 /* return current register mapping */
922 void *si_coreregs(si_t
*sih
)
927 ASSERT(GOODREGS(sii
->curmap
));
933 * This function changes logical "focus" to the indicated core;
934 * must be called with interrupts off.
935 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
937 void *si_setcore(si_t
*sih
, uint coreid
, uint coreunit
)
941 idx
= si_findcoreidx(sih
, coreid
, coreunit
);
945 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
946 return ai_setcoreidx(sih
, idx
);
949 return sb_setcoreidx(sih
, idx
);
958 void *si_setcoreidx(si_t
*sih
, uint coreidx
)
960 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
961 return ai_setcoreidx(sih
, coreidx
);
969 /* Turn off interrupt as required by sb_setcore, before switch core */
970 void *si_switch_core(si_t
*sih
, uint coreid
, uint
*origidx
, uint
*intr_val
)
978 /* Overloading the origidx variable to remember the coreid,
979 * this works because the core ids cannot be confused with
983 if (coreid
== CC_CORE_ID
)
984 return (void *)CCREGS_FAST(sii
);
985 else if (coreid
== sih
->buscoretype
)
986 return (void *)PCIEREGS(sii
);
988 INTR_OFF(sii
, *intr_val
);
989 *origidx
= sii
->curidx
;
990 cc
= si_setcore(sih
, coreid
, 0);
996 /* restore coreidx and restore interrupt */
997 void si_restore_core(si_t
*sih
, uint coreid
, uint intr_val
)
1003 && ((coreid
== CC_CORE_ID
) || (coreid
== sih
->buscoretype
)))
1006 si_setcoreidx(sih
, coreid
);
1007 INTR_RESTORE(sii
, intr_val
);
1010 int si_numaddrspaces(si_t
*sih
)
1012 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1013 return ai_numaddrspaces(sih
);
1020 uint32
si_addrspace(si_t
*sih
, uint asidx
)
1022 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1023 return ai_addrspace(sih
, asidx
);
1030 uint32
si_addrspacesize(si_t
*sih
, uint asidx
)
1032 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1033 return ai_addrspacesize(sih
, asidx
);
1040 uint32
si_core_cflags(si_t
*sih
, uint32 mask
, uint32 val
)
1042 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1043 return ai_core_cflags(sih
, mask
, val
);
1050 void si_core_cflags_wo(si_t
*sih
, uint32 mask
, uint32 val
)
1052 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1053 ai_core_cflags_wo(sih
, mask
, val
);
1058 uint32
si_core_sflags(si_t
*sih
, uint32 mask
, uint32 val
)
1060 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1061 return ai_core_sflags(sih
, mask
, val
);
1068 bool si_iscoreup(si_t
*sih
)
1070 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1071 return ai_iscoreup(sih
);
1074 return sb_iscoreup(sih
);
1082 void si_write_wrapperreg(si_t
*sih
, uint32 offset
, uint32 val
)
1084 /* only for 4319, no requirement for SOCI_SB */
1085 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
) {
1086 ai_write_wrap_reg(sih
, offset
, val
);
1090 uint
si_corereg(si_t
*sih
, uint coreidx
, uint regoff
, uint mask
, uint val
)
1093 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1094 return ai_corereg(sih
, coreidx
, regoff
, mask
, val
);
1097 return sb_corereg(sih
, coreidx
, regoff
, mask
, val
);
1105 void si_core_disable(si_t
*sih
, uint32 bits
)
1108 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1109 ai_core_disable(sih
, bits
);
1112 sb_core_disable(sih
, bits
);
1116 void si_core_reset(si_t
*sih
, uint32 bits
, uint32 resetbits
)
1118 if (CHIPTYPE(sih
->socitype
) == SOCI_AI
)
1119 ai_core_reset(sih
, bits
, resetbits
);
1122 sb_core_reset(sih
, bits
, resetbits
);
1126 /* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1127 int si_corebist(si_t
*sih
)
1132 /* Read core control flags */
1133 cflags
= si_core_cflags(sih
, 0, 0);
1135 /* Set bist & fgc */
1136 si_core_cflags(sih
, ~0, (SICF_BIST_EN
| SICF_FGC
));
1138 /* Wait for bist done */
1139 SPINWAIT(((si_core_sflags(sih
, 0, 0) & SISF_BIST_DONE
) == 0), 100000);
1141 if (si_core_sflags(sih
, 0, 0) & SISF_BIST_ERROR
)
1142 result
= BCME_ERROR
;
1144 /* Reset core control flags */
1145 si_core_cflags(sih
, 0xffff, cflags
);
1150 static uint32
BCMINITFN(factor6
) (uint32 x
)
1170 /* calculate the speed the SI would run at given a set of clockcontrol values */
1171 uint32
BCMINITFN(si_clock_rate
) (uint32 pll_type
, uint32 n
, uint32 m
)
1173 uint32 n1
, n2
, clock
, m1
, m2
, m3
, mc
;
1175 n1
= n
& CN_N1_MASK
;
1176 n2
= (n
& CN_N2_MASK
) >> CN_N2_SHIFT
;
1178 if (pll_type
== PLL_TYPE6
) {
1179 if (m
& CC_T6_MMASK
)
1183 } else if ((pll_type
== PLL_TYPE1
) ||
1184 (pll_type
== PLL_TYPE3
) ||
1185 (pll_type
== PLL_TYPE4
) || (pll_type
== PLL_TYPE7
)) {
1188 } else if (pll_type
== PLL_TYPE2
) {
1191 ASSERT((n1
>= 2) && (n1
<= 7));
1192 ASSERT((n2
>= 5) && (n2
<= 23));
1193 } else if (pll_type
== PLL_TYPE5
) {
1197 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1198 if ((pll_type
== PLL_TYPE3
) || (pll_type
== PLL_TYPE7
)) {
1199 clock
= CC_CLOCK_BASE2
* n1
* n2
;
1201 clock
= CC_CLOCK_BASE1
* n1
* n2
;
1206 m1
= m
& CC_M1_MASK
;
1207 m2
= (m
& CC_M2_MASK
) >> CC_M2_SHIFT
;
1208 m3
= (m
& CC_M3_MASK
) >> CC_M3_SHIFT
;
1209 mc
= (m
& CC_MC_MASK
) >> CC_MC_SHIFT
;
1211 if ((pll_type
== PLL_TYPE1
) ||
1212 (pll_type
== PLL_TYPE3
) ||
1213 (pll_type
== PLL_TYPE4
) || (pll_type
== PLL_TYPE7
)) {
1215 if ((pll_type
== PLL_TYPE1
) || (pll_type
== PLL_TYPE3
))
1227 return clock
/ (m1
* m2
);
1229 return clock
/ (m1
* m2
* m3
);
1231 return clock
/ (m1
* m3
);
1236 ASSERT(pll_type
== PLL_TYPE2
);
1241 ASSERT((m1
>= 2) && (m1
<= 7));
1242 ASSERT((m2
>= 3) && (m2
<= 10));
1243 ASSERT((m3
>= 2) && (m3
<= 7));
1245 if ((mc
& CC_T2MC_M1BYP
) == 0)
1247 if ((mc
& CC_T2MC_M2BYP
) == 0)
1249 if ((mc
& CC_T2MC_M3BYP
) == 0)
1256 uint32
BCMINITFN(si_clock
) (si_t
*sih
)
1262 uint32 pll_type
, rate
;
1266 INTR_OFF(sii
, intr_val
);
1267 if (PMUCTL_ENAB(sih
)) {
1268 rate
= si_pmu_si_clock(sih
, sii
->osh
);
1273 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
1276 n
= R_REG(sii
->osh
, &cc
->clockcontrol_n
);
1277 pll_type
= sih
->cccaps
& CC_CAP_PLL_MASK
;
1278 if (pll_type
== PLL_TYPE6
)
1279 m
= R_REG(sii
->osh
, &cc
->clockcontrol_m3
);
1280 else if (pll_type
== PLL_TYPE3
)
1281 m
= R_REG(sii
->osh
, &cc
->clockcontrol_m2
);
1283 m
= R_REG(sii
->osh
, &cc
->clockcontrol_sb
);
1285 /* calculate rate */
1286 rate
= si_clock_rate(pll_type
, n
, m
);
1288 if (pll_type
== PLL_TYPE3
)
1291 /* switch back to previous core */
1292 si_setcoreidx(sih
, idx
);
1294 INTR_RESTORE(sii
, intr_val
);
1299 uint32
BCMINITFN(si_alp_clock
) (si_t
*sih
)
1301 if (PMUCTL_ENAB(sih
))
1302 return si_pmu_alp_clock(sih
, si_osh(sih
));
1307 uint32
BCMINITFN(si_ilp_clock
) (si_t
*sih
)
1309 if (PMUCTL_ENAB(sih
))
1310 return si_pmu_ilp_clock(sih
, si_osh(sih
));
1315 /* set chip watchdog reset timer to fire in 'ticks' */
1318 si_watchdog(si_t
*sih
, uint ticks
)
1320 if (PMUCTL_ENAB(sih
)) {
1322 if ((sih
->chip
== BCM4319_CHIP_ID
) && (sih
->chiprev
== 0) &&
1324 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
,
1325 clk_ctl_st
), ~0, 0x2);
1326 si_setcore(sih
, USB20D_CORE_ID
, 0);
1327 si_core_disable(sih
, 1);
1328 si_setcore(sih
, CC_CORE_ID
, 0);
1333 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, pmuwatchdog
),
1337 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, watchdog
),
1342 void si_watchdog(si_t
*sih
, uint ticks
)
1346 if (PMUCTL_ENAB(sih
)) {
1348 if ((CHIPID(sih
->chip
) == BCM4319_CHIP_ID
) &&
1349 (CHIPREV(sih
->chiprev
) == 0) && (ticks
!= 0)) {
1350 si_corereg(sih
, SI_CC_IDX
,
1351 OFFSETOF(chipcregs_t
, clk_ctl_st
), ~0, 0x2);
1352 si_setcore(sih
, USB20D_CORE_ID
, 0);
1353 si_core_disable(sih
, 1);
1354 si_setcore(sih
, CC_CORE_ID
, 0);
1357 nb
= (sih
->ccrev
< 26) ? 16 : ((sih
->ccrev
>= 37) ? 32 : 24);
1358 /* The mips compiler uses the sllv instruction,
1359 * so we specially handle the 32-bit case.
1364 maxt
= ((1 << nb
) - 1);
1368 else if (ticks
> maxt
)
1371 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, pmuwatchdog
),
1374 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1375 si_clkctl_cc(sih
, ticks
? CLK_FAST
: CLK_DYNAMIC
);
1376 maxt
= (1 << 28) - 1;
1380 si_corereg(sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, watchdog
), ~0,
1386 /* trigger watchdog reset after ms milliseconds */
1387 void si_watchdog_ms(si_t
*sih
, uint32 ms
)
1389 si_watchdog(sih
, wd_msticks
* ms
);
1392 uint16
BCMATTACHFN(si_d11_devid
) (si_t
*sih
)
1394 si_info_t
*sii
= SI_INFO(sih
);
1397 /* normal case: nvram variable with devpath->devid->wl0id */
1398 device
= (uint16
) si_getdevpathintvar(sih
, "devid");
1402 /* Get devid from OTP/SPROM depending on where the SROM is read */
1403 device
= (uint16
) getintvar(sii
->vars
, "devid");
1407 /* no longer support wl0id, but keep the code here for backward compatibility. */
1408 device
= (uint16
) getintvar(sii
->vars
, "wl0id");
1419 /* return the slow clock source - LPO, XTAL, or PCI */
1420 static uint
si_slowclk_src(si_info_t
*sii
)
1424 ASSERT(SI_FAST(sii
) || si_coreid(&sii
->pub
) == CC_CORE_ID
);
1426 if (sii
->pub
.ccrev
< 6) {
1427 if ((BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
) &&
1428 (OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
))
1429 & PCI_CFG_GPIO_SCS
))
1433 } else if (sii
->pub
.ccrev
< 10) {
1434 cc
= (chipcregs_t
*) si_setcoreidx(&sii
->pub
, sii
->curidx
);
1435 return R_REG(sii
->osh
, &cc
->slow_clk_ctl
) & SCC_SS_MASK
;
1436 } else /* Insta-clock */
1440 /* return the ILP (slowclock) min or max frequency */
1441 static uint
si_slowclk_freq(si_info_t
*sii
, bool max_freq
, chipcregs_t
*cc
)
1446 ASSERT(SI_FAST(sii
) || si_coreid(&sii
->pub
) == CC_CORE_ID
);
1448 /* shouldn't be here unless we've established the chip has dynamic clk control */
1449 ASSERT(R_REG(sii
->osh
, &cc
->capabilities
) & CC_CAP_PWR_CTL
);
1451 slowclk
= si_slowclk_src(sii
);
1452 if (sii
->pub
.ccrev
< 6) {
1453 if (slowclk
== SCC_SS_PCI
)
1454 return max_freq
? (PCIMAXFREQ
/ 64)
1455 : (PCIMINFREQ
/ 64);
1457 return max_freq
? (XTALMAXFREQ
/ 32)
1458 : (XTALMINFREQ
/ 32);
1459 } else if (sii
->pub
.ccrev
< 10) {
1461 (((R_REG(sii
->osh
, &cc
->slow_clk_ctl
) & SCC_CD_MASK
) >>
1463 if (slowclk
== SCC_SS_LPO
)
1464 return max_freq
? LPOMAXFREQ
: LPOMINFREQ
;
1465 else if (slowclk
== SCC_SS_XTAL
)
1466 return max_freq
? (XTALMAXFREQ
/ div
)
1467 : (XTALMINFREQ
/ div
);
1468 else if (slowclk
== SCC_SS_PCI
)
1469 return max_freq
? (PCIMAXFREQ
/ div
)
1470 : (PCIMINFREQ
/ div
);
1474 /* Chipc rev 10 is InstaClock */
1475 div
= R_REG(sii
->osh
, &cc
->system_clk_ctl
) >> SYCC_CD_SHIFT
;
1476 div
= 4 * (div
+ 1);
1477 return max_freq
? XTALMAXFREQ
: (XTALMINFREQ
/ div
);
1482 static void BCMINITFN(si_clkctl_setdelay
) (si_info_t
*sii
, void *chipcregs
)
1484 chipcregs_t
*cc
= (chipcregs_t
*) chipcregs
;
1485 uint slowmaxfreq
, pll_delay
, slowclk
;
1486 uint pll_on_delay
, fref_sel_delay
;
1488 pll_delay
= PLL_DELAY
;
1490 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1491 * since the xtal will also be powered down by dynamic clk control logic.
1494 slowclk
= si_slowclk_src(sii
);
1495 if (slowclk
!= SCC_SS_XTAL
)
1496 pll_delay
+= XTAL_ON_DELAY
;
1498 /* Starting with 4318 it is ILP that is used for the delays */
1500 si_slowclk_freq(sii
, (sii
->pub
.ccrev
>= 10) ? FALSE
: TRUE
, cc
);
1502 pll_on_delay
= ((slowmaxfreq
* pll_delay
) + 999999) / 1000000;
1503 fref_sel_delay
= ((slowmaxfreq
* FREF_DELAY
) + 999999) / 1000000;
1505 W_REG(sii
->osh
, &cc
->pll_on_delay
, pll_on_delay
);
1506 W_REG(sii
->osh
, &cc
->fref_sel_delay
, fref_sel_delay
);
1509 /* initialize power control delay registers */
1510 void BCMINITFN(si_clkctl_init
) (si_t
*sih
)
1517 if (!CCCTL_ENAB(sih
))
1521 fast
= SI_FAST(sii
);
1523 origidx
= sii
->curidx
;
1524 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
1528 cc
= (chipcregs_t
*) CCREGS_FAST(sii
);
1534 /* set all Instaclk chip ILP to 1 MHz */
1535 if (sih
->ccrev
>= 10)
1536 SET_REG(sii
->osh
, &cc
->system_clk_ctl
, SYCC_CD_MASK
,
1537 (ILP_DIV_1MHZ
<< SYCC_CD_SHIFT
));
1539 si_clkctl_setdelay(sii
, (void *)(uintptr
) cc
);
1542 si_setcoreidx(sih
, origidx
);
1545 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1546 uint16
BCMINITFN(si_clkctl_fast_pwrup_delay
) (si_t
*sih
)
1557 if (PMUCTL_ENAB(sih
)) {
1558 INTR_OFF(sii
, intr_val
);
1559 fpdelay
= si_pmu_fast_pwrup_delay(sih
, sii
->osh
);
1560 INTR_RESTORE(sii
, intr_val
);
1564 if (!CCCTL_ENAB(sih
))
1567 fast
= SI_FAST(sii
);
1570 origidx
= sii
->curidx
;
1571 INTR_OFF(sii
, intr_val
);
1572 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
1576 cc
= (chipcregs_t
*) CCREGS_FAST(sii
);
1582 slowminfreq
= si_slowclk_freq(sii
, FALSE
, cc
);
1583 fpdelay
= (((R_REG(sii
->osh
, &cc
->pll_on_delay
) + 2) * 1000000) +
1584 (slowminfreq
- 1)) / slowminfreq
;
1588 si_setcoreidx(sih
, origidx
);
1589 INTR_RESTORE(sii
, intr_val
);
1594 /* turn primary xtal and/or pll off/on */
1595 int si_clkctl_xtal(si_t
*sih
, uint what
, bool on
)
1598 uint32 in
, out
, outen
;
1602 switch (BUSTYPE(sih
->bustype
)) {
1607 #endif /* BCMSDIO */
1610 /* pcie core doesn't have any mapping to control the xtal pu */
1614 in
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_IN
, sizeof(uint32
));
1616 OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUT
, sizeof(uint32
));
1618 OSL_PCI_READ_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
,
1622 * Avoid glitching the clock if GPRS is already using it.
1623 * We can't actually read the state of the PLLPD so we infer it
1624 * by the value of XTAL_PU which *is* readable via gpioin.
1626 if (on
&& (in
& PCI_CFG_GPIO_XTAL
))
1630 outen
|= PCI_CFG_GPIO_XTAL
;
1632 outen
|= PCI_CFG_GPIO_PLL
;
1635 /* turn primary xtal on */
1637 out
|= PCI_CFG_GPIO_XTAL
;
1639 out
|= PCI_CFG_GPIO_PLL
;
1640 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
,
1641 sizeof(uint32
), out
);
1642 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
,
1643 sizeof(uint32
), outen
);
1644 OSL_DELAY(XTAL_ON_DELAY
);
1649 out
&= ~PCI_CFG_GPIO_PLL
;
1650 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
,
1651 sizeof(uint32
), out
);
1656 out
&= ~PCI_CFG_GPIO_XTAL
;
1658 out
|= PCI_CFG_GPIO_PLL
;
1659 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUT
,
1660 sizeof(uint32
), out
);
1661 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_GPIO_OUTEN
,
1662 sizeof(uint32
), outen
);
1673 * clock control policy function throught chipcommon
1675 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1676 * returns true if we are forcing fast clock
1677 * this is a wrapper over the next internal function
1678 * to allow flexible policy settings for outside caller
1680 bool si_clkctl_cc(si_t
*sih
, uint mode
)
1686 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1690 if (PCI_FORCEHT(sii
))
1691 return mode
== CLK_FAST
;
1693 return _si_clkctl_cc(sii
, mode
);
1696 /* clk control mechanism through chipcommon, no policy checking */
1697 static bool _si_clkctl_cc(si_info_t
*sii
, uint mode
)
1703 bool fast
= SI_FAST(sii
);
1705 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1706 if (sii
->pub
.ccrev
< 6)
1709 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1710 ASSERT(sii
->pub
.ccrev
!= 10);
1713 INTR_OFF(sii
, intr_val
);
1714 origidx
= sii
->curidx
;
1716 if ((BUSTYPE(sii
->pub
.bustype
) == SI_BUS
) &&
1717 si_setcore(&sii
->pub
, MIPS33_CORE_ID
, 0) &&
1718 (si_corerev(&sii
->pub
) <= 7) && (sii
->pub
.ccrev
>= 10))
1721 cc
= (chipcregs_t
*) si_setcore(&sii
->pub
, CC_CORE_ID
, 0);
1723 cc
= (chipcregs_t
*) CCREGS_FAST(sii
);
1729 if (!CCCTL_ENAB(&sii
->pub
) && (sii
->pub
.ccrev
< 20))
1733 case CLK_FAST
: /* FORCEHT, fast (pll) clock */
1734 if (sii
->pub
.ccrev
< 10) {
1735 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1736 si_clkctl_xtal(&sii
->pub
, XTAL
, ON
);
1737 SET_REG(sii
->osh
, &cc
->slow_clk_ctl
,
1738 (SCC_XC
| SCC_FS
| SCC_IP
), SCC_IP
);
1739 } else if (sii
->pub
.ccrev
< 20) {
1740 OR_REG(sii
->osh
, &cc
->system_clk_ctl
, SYCC_HR
);
1742 OR_REG(sii
->osh
, &cc
->clk_ctl_st
, CCS_FORCEHT
);
1745 /* wait for the PLL */
1746 if (PMUCTL_ENAB(&sii
->pub
)) {
1747 uint32 htavail
= CCS_HTAVAIL
;
1748 SPINWAIT(((R_REG(sii
->osh
, &cc
->clk_ctl_st
) & htavail
)
1749 == 0), PMU_MAX_TRANSITION_DLY
);
1750 ASSERT(R_REG(sii
->osh
, &cc
->clk_ctl_st
) & htavail
);
1752 OSL_DELAY(PLL_DELAY
);
1756 case CLK_DYNAMIC
: /* enable dynamic clock control */
1757 if (sii
->pub
.ccrev
< 10) {
1758 scc
= R_REG(sii
->osh
, &cc
->slow_clk_ctl
);
1759 scc
&= ~(SCC_FS
| SCC_IP
| SCC_XC
);
1760 if ((scc
& SCC_SS_MASK
) != SCC_SS_XTAL
)
1762 W_REG(sii
->osh
, &cc
->slow_clk_ctl
, scc
);
1764 /* for dynamic control, we have to release our xtal_pu "force on" */
1766 si_clkctl_xtal(&sii
->pub
, XTAL
, OFF
);
1767 } else if (sii
->pub
.ccrev
< 20) {
1769 AND_REG(sii
->osh
, &cc
->system_clk_ctl
, ~SYCC_HR
);
1771 AND_REG(sii
->osh
, &cc
->clk_ctl_st
, ~CCS_FORCEHT
);
1781 si_setcoreidx(&sii
->pub
, origidx
);
1782 INTR_RESTORE(sii
, intr_val
);
1784 return mode
== CLK_FAST
;
1787 /* Build device path. Support SI, PCI, and JTAG for now. */
1788 int BCMATTACHFN(si_devpath
) (si_t
*sih
, char *path
, int size
)
1792 ASSERT(path
!= NULL
);
1793 ASSERT(size
>= SI_DEVPATH_BUFSZ
);
1795 if (!path
|| size
<= 0)
1798 switch (BUSTYPE(sih
->bustype
)) {
1801 slen
= snprintf(path
, (size_t) size
, "sb/%u/", si_coreidx(sih
));
1804 ASSERT((SI_INFO(sih
))->osh
!= NULL
);
1805 slen
= snprintf(path
, (size_t) size
, "pci/%u/%u/",
1806 OSL_PCI_BUS((SI_INFO(sih
))->osh
),
1807 OSL_PCI_SLOT((SI_INFO(sih
))->osh
));
1812 SI_ERROR(("si_devpath: device 0 assumed\n"));
1813 slen
= snprintf(path
, (size_t) size
, "sd/%u/", si_coreidx(sih
));
1822 if (slen
< 0 || slen
>= size
) {
1830 /* Get a variable, but only if it has a devpath prefix */
1831 char *BCMATTACHFN(si_getdevpathvar
) (si_t
*sih
, const char *name
)
1833 char varname
[SI_DEVPATH_BUFSZ
+ 32];
1835 si_devpathvar(sih
, varname
, sizeof(varname
), name
);
1837 return getvar(NULL
, varname
);
1840 /* Get a variable, but only if it has a devpath prefix */
1841 int BCMATTACHFN(si_getdevpathintvar
) (si_t
*sih
, const char *name
)
1843 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
1844 return getintvar(NULL
, name
);
1846 char varname
[SI_DEVPATH_BUFSZ
+ 32];
1848 si_devpathvar(sih
, varname
, sizeof(varname
), name
);
1850 return getintvar(NULL
, varname
);
1854 char *si_getnvramflvar(si_t
*sih
, const char *name
)
1856 return getvar(NULL
, name
);
1859 /* Concatenate the dev path with a varname into the given 'var' buffer
1860 * and return the 'var' pointer.
1861 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1862 * On overflow, the first char will be set to '\0'.
1864 static char *BCMATTACHFN(si_devpathvar
) (si_t
*sih
, char *var
, int len
,
1868 if (!var
|| len
<= 0)
1871 if (si_devpath(sih
, var
, len
) == 0) {
1872 path_len
= strlen(var
);
1874 if (strlen(name
) + 1 > (uint
) (len
- path_len
))
1877 strncpy(var
+ path_len
, name
, len
- path_len
- 1);
1883 uint32
si_pciereg(si_t
*sih
, uint32 offset
, uint32 mask
, uint32 val
, uint type
)
1890 SI_ERROR(("%s: Not a PCIE device\n", __func__
));
1894 return pcicore_pciereg(sii
->pch
, offset
, mask
, val
, type
);
1898 si_pcieserdesreg(si_t
*sih
, uint32 mdioslave
, uint32 offset
, uint32 mask
,
1906 SI_ERROR(("%s: Not a PCIE device\n", __func__
));
1910 return pcicore_pcieserdesreg(sii
->pch
, mdioslave
, offset
, mask
, val
);
1914 /* return TRUE if PCIE capability exists in the pci config space */
1915 static __used
bool si_ispcie(si_info_t
*sii
)
1919 if (BUSTYPE(sii
->pub
.bustype
) != PCI_BUS
)
1923 pcicore_find_pci_capability(sii
->osh
, PCI_CAP_PCIECAP_ID
, NULL
,
1931 /* Wake-on-wireless-LAN (WOWL) support functions */
1932 /* Enable PME generation and disable clkreq */
1933 void si_pci_pmeen(si_t
*sih
)
1939 pcicore_pmeen(sii
->pch
);
1942 /* Return TRUE if PME status is set */
1943 bool si_pci_pmestat(si_t
*sih
)
1949 return pcicore_pmestat(sii
->pch
);
1952 /* Disable PME generation, clear the PME status bit if set */
1953 void si_pci_pmeclr(si_t
*sih
)
1959 pcicore_pmeclr(sii
->pch
);
1963 /* initialize the sdio core */
1964 void si_sdio_init(si_t
*sih
)
1966 si_info_t
*sii
= SI_INFO(sih
);
1968 if (((sih
->buscoretype
== PCMCIA_CORE_ID
) && (sih
->buscorerev
>= 8)) ||
1969 (sih
->buscoretype
== SDIOD_CORE_ID
)) {
1971 sdpcmd_regs_t
*sdpregs
;
1973 /* get the current core index */
1975 ASSERT(idx
== si_findcoreidx(sih
, D11_CORE_ID
, 0));
1977 /* switch to sdio core */
1978 sdpregs
= (sdpcmd_regs_t
*) si_setcore(sih
, PCMCIA_CORE_ID
, 0);
1981 (sdpcmd_regs_t
*) si_setcore(sih
, SDIOD_CORE_ID
, 0);
1984 SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih
->buscorerev
, idx
, sii
->curidx
, sdpregs
));
1986 /* enable backplane error and core interrupts */
1987 W_REG(sii
->osh
, &sdpregs
->hostintmask
, I_SBINT
);
1988 W_REG(sii
->osh
, &sdpregs
->sbintmask
,
1989 (I_SB_SERR
| I_SB_RESPERR
| (1 << idx
)));
1991 /* switch back to previous core */
1992 si_setcoreidx(sih
, idx
);
1995 /* enable interrupts */
1996 bcmsdh_intr_enable(sii
->sdh
);
1999 #endif /* BCMSDIO */
2001 bool BCMATTACHFN(si_pci_war16165
) (si_t
*sih
)
2007 return PCI(sii
) && (sih
->buscorerev
<= 10);
2010 /* Disable pcie_war_ovr for some platforms (sigh!)
2011 * This is for boards that have BFL2_PCIEWAR_OVR set
2012 * but are in systems that still want the benefits of ASPM
2013 * Note that this should be done AFTER si_doattach
2015 void si_pcie_war_ovr_update(si_t
*sih
, u8 aspm
)
2024 pcie_war_ovr_aspm_update(sii
->pch
, aspm
);
2027 /* back door for other module to override chippkg */
2028 void si_chippkg_set(si_t
*sih
, uint val
)
2034 sii
->pub
.chippkg
= val
;
2037 void BCMINITFN(si_pci_up
) (si_t
*sih
)
2043 /* if not pci bus, we're done */
2044 if (BUSTYPE(sih
->bustype
) != PCI_BUS
)
2047 if (PCI_FORCEHT(sii
))
2048 _si_clkctl_cc(sii
, CLK_FAST
);
2051 pcicore_up(sii
->pch
, SI_PCIUP
);
2055 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
2056 void BCMUNINITFN(si_pci_sleep
) (si_t
*sih
)
2062 pcicore_sleep(sii
->pch
);
2065 /* Unconfigure and/or apply various WARs when going down */
2066 void BCMINITFN(si_pci_down
) (si_t
*sih
)
2072 /* if not pci bus, we're done */
2073 if (BUSTYPE(sih
->bustype
) != PCI_BUS
)
2076 /* release FORCEHT since chip is going to "down" state */
2077 if (PCI_FORCEHT(sii
))
2078 _si_clkctl_cc(sii
, CLK_DYNAMIC
);
2080 pcicore_down(sii
->pch
, SI_PCIDOWN
);
2084 * Configure the pci core for pci client (NIC) action
2085 * coremask is the bitvec of cores by index to be enabled.
2087 void BCMATTACHFN(si_pci_setup
) (si_t
*sih
, uint coremask
)
2090 sbpciregs_t
*pciregs
= NULL
;
2091 uint32 siflag
= 0, w
;
2096 if (BUSTYPE(sii
->pub
.bustype
) != PCI_BUS
)
2099 ASSERT(PCI(sii
) || PCIE(sii
));
2100 ASSERT(sii
->pub
.buscoreidx
!= BADIDX
);
2103 /* get current core index */
2106 /* we interrupt on this backplane flag number */
2107 siflag
= si_flag(sih
);
2109 /* switch over to pci core */
2111 (sbpciregs_t
*) si_setcoreidx(sih
, sii
->pub
.buscoreidx
);
2115 * Enable sb->pci interrupts. Assume
2116 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2118 if (PCIE(sii
) || (PCI(sii
) && ((sii
->pub
.buscorerev
) >= 6))) {
2119 /* pci config write to set this core bit in PCIIntMask */
2120 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_INT_MASK
, sizeof(uint32
));
2121 w
|= (coremask
<< PCI_SBIM_SHIFT
);
2122 OSL_PCI_WRITE_CONFIG(sii
->osh
, PCI_INT_MASK
, sizeof(uint32
), w
);
2124 /* set sbintvec bit for our flag number */
2125 si_setint(sih
, siflag
);
2129 OR_REG(sii
->osh
, &pciregs
->sbtopci2
,
2130 (SBTOPCI_PREF
| SBTOPCI_BURST
));
2131 if (sii
->pub
.buscorerev
>= 11) {
2132 OR_REG(sii
->osh
, &pciregs
->sbtopci2
,
2133 SBTOPCI_RC_READMULTI
);
2134 w
= R_REG(sii
->osh
, &pciregs
->clkrun
);
2135 W_REG(sii
->osh
, &pciregs
->clkrun
,
2136 (w
| PCI_CLKRUN_DSBL
));
2137 w
= R_REG(sii
->osh
, &pciregs
->clkrun
);
2140 /* switch back to previous core */
2141 si_setcoreidx(sih
, idx
);
2145 u8
si_pcieclkreq(si_t
*sih
, uint32 mask
, uint32 val
)
2153 return pcie_clkreq(sii
->pch
, mask
, val
);
2156 uint32
si_pcielcreg(si_t
*sih
, uint32 mask
, uint32 val
)
2165 return pcie_lcreg(sii
->pch
, mask
, val
);
2168 /* indirect way to read pcie config regs */
2169 uint
si_pcie_readreg(void *sih
, uint addrtype
, uint offset
)
2171 return pcie_readreg(((si_info_t
*) sih
)->osh
,
2172 (sbpcieregs_t
*) PCIEREGS(((si_info_t
*) sih
)),
2177 * Fixup SROMless PCI device's configuration.
2178 * The current core may be changed upon return.
2180 int si_pci_fixcfg(si_t
*sih
)
2182 uint origidx
, pciidx
;
2183 sbpciregs_t
*pciregs
= NULL
;
2184 sbpcieregs_t
*pcieregs
= NULL
;
2186 uint16 val16
, *reg16
= NULL
;
2188 si_info_t
*sii
= SI_INFO(sih
);
2190 ASSERT(BUSTYPE(sii
->pub
.bustype
) == PCI_BUS
);
2192 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
2193 /* save the current index */
2194 origidx
= si_coreidx(&sii
->pub
);
2196 /* check 'pi' is correct and fix it if not */
2197 if (sii
->pub
.buscoretype
== PCIE_CORE_ID
) {
2199 (sbpcieregs_t
*) si_setcore(&sii
->pub
, PCIE_CORE_ID
, 0);
2201 ASSERT(pcieregs
!= NULL
);
2202 reg16
= &pcieregs
->sprom
[SRSH_PI_OFFSET
];
2203 } else if (sii
->pub
.buscoretype
== PCI_CORE_ID
) {
2204 pciregs
= (sbpciregs_t
*) si_setcore(&sii
->pub
, PCI_CORE_ID
, 0);
2206 ASSERT(pciregs
!= NULL
);
2207 reg16
= &pciregs
->sprom
[SRSH_PI_OFFSET
];
2209 pciidx
= si_coreidx(&sii
->pub
);
2210 val16
= R_REG(sii
->osh
, reg16
);
2211 if (((val16
& SRSH_PI_MASK
) >> SRSH_PI_SHIFT
) != (uint16
) pciidx
) {
2213 (uint16
) (pciidx
<< SRSH_PI_SHIFT
) | (val16
&
2215 W_REG(sii
->osh
, reg16
, val16
);
2218 /* restore the original index */
2219 si_setcoreidx(&sii
->pub
, origidx
);
2221 pcicore_hwup(sii
->pch
);
2225 /* change logical "focus" to the gpio core for optimized access */
2226 void *si_gpiosetcore(si_t
*sih
)
2228 return si_setcoreidx(sih
, SI_CC_IDX
);
2231 /* mask&set gpiocontrol bits */
2232 uint32
si_gpiocontrol(si_t
*sih
, uint32 mask
, uint32 val
, u8 priority
)
2238 /* gpios could be shared on router platforms
2239 * ignore reservation if it's high priority (e.g., test apps)
2241 if ((priority
!= GPIO_HI_PRIORITY
) &&
2242 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2243 mask
= priority
? (si_gpioreservation
& mask
) :
2244 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2248 regoff
= OFFSETOF(chipcregs_t
, gpiocontrol
);
2249 return si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
);
2252 /* mask&set gpio output enable bits */
2253 uint32
si_gpioouten(si_t
*sih
, uint32 mask
, uint32 val
, u8 priority
)
2259 /* gpios could be shared on router platforms
2260 * ignore reservation if it's high priority (e.g., test apps)
2262 if ((priority
!= GPIO_HI_PRIORITY
) &&
2263 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2264 mask
= priority
? (si_gpioreservation
& mask
) :
2265 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2269 regoff
= OFFSETOF(chipcregs_t
, gpioouten
);
2270 return si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
);
2273 /* mask&set gpio output bits */
2274 uint32
si_gpioout(si_t
*sih
, uint32 mask
, uint32 val
, u8 priority
)
2280 /* gpios could be shared on router platforms
2281 * ignore reservation if it's high priority (e.g., test apps)
2283 if ((priority
!= GPIO_HI_PRIORITY
) &&
2284 (BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2285 mask
= priority
? (si_gpioreservation
& mask
) :
2286 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2290 regoff
= OFFSETOF(chipcregs_t
, gpioout
);
2291 return si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
);
2294 /* reserve one gpio */
2295 uint32
si_gpioreserve(si_t
*sih
, uint32 gpio_bitmask
, u8 priority
)
2301 /* only cores on SI_BUS share GPIO's and only applcation users need to
2302 * reserve/release GPIO
2304 if ((BUSTYPE(sih
->bustype
) != SI_BUS
) || (!priority
)) {
2305 ASSERT((BUSTYPE(sih
->bustype
) == SI_BUS
) && (priority
));
2308 /* make sure only one bit is set */
2309 if ((!gpio_bitmask
) || ((gpio_bitmask
) & (gpio_bitmask
- 1))) {
2310 ASSERT((gpio_bitmask
)
2311 && !((gpio_bitmask
) & (gpio_bitmask
- 1)));
2315 /* already reserved */
2316 if (si_gpioreservation
& gpio_bitmask
)
2318 /* set reservation */
2319 si_gpioreservation
|= gpio_bitmask
;
2321 return si_gpioreservation
;
2324 /* release one gpio */
2326 * releasing the gpio doesn't change the current value on the GPIO last write value
2327 * persists till some one overwrites it
2330 uint32
si_gpiorelease(si_t
*sih
, uint32 gpio_bitmask
, u8 priority
)
2336 /* only cores on SI_BUS share GPIO's and only applcation users need to
2337 * reserve/release GPIO
2339 if ((BUSTYPE(sih
->bustype
) != SI_BUS
) || (!priority
)) {
2340 ASSERT((BUSTYPE(sih
->bustype
) == SI_BUS
) && (priority
));
2343 /* make sure only one bit is set */
2344 if ((!gpio_bitmask
) || ((gpio_bitmask
) & (gpio_bitmask
- 1))) {
2345 ASSERT((gpio_bitmask
)
2346 && !((gpio_bitmask
) & (gpio_bitmask
- 1)));
2350 /* already released */
2351 if (!(si_gpioreservation
& gpio_bitmask
))
2354 /* clear reservation */
2355 si_gpioreservation
&= ~gpio_bitmask
;
2357 return si_gpioreservation
;
2360 /* return the current gpioin register value */
2361 uint32
si_gpioin(si_t
*sih
)
2369 regoff
= OFFSETOF(chipcregs_t
, gpioin
);
2370 return si_corereg(sih
, SI_CC_IDX
, regoff
, 0, 0);
2373 /* mask&set gpio interrupt polarity bits */
2374 uint32
si_gpiointpolarity(si_t
*sih
, uint32 mask
, uint32 val
, u8 priority
)
2382 /* gpios could be shared on router platforms */
2383 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2384 mask
= priority
? (si_gpioreservation
& mask
) :
2385 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2389 regoff
= OFFSETOF(chipcregs_t
, gpiointpolarity
);
2390 return si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
);
2393 /* mask&set gpio interrupt mask bits */
2394 uint32
si_gpiointmask(si_t
*sih
, uint32 mask
, uint32 val
, u8 priority
)
2402 /* gpios could be shared on router platforms */
2403 if ((BUSTYPE(sih
->bustype
) == SI_BUS
) && (val
|| mask
)) {
2404 mask
= priority
? (si_gpioreservation
& mask
) :
2405 ((si_gpioreservation
| mask
) & ~(si_gpioreservation
));
2409 regoff
= OFFSETOF(chipcregs_t
, gpiointmask
);
2410 return si_corereg(sih
, SI_CC_IDX
, regoff
, mask
, val
);
2413 /* assign the gpio to an led */
2414 uint32
si_gpioled(si_t
*sih
, uint32 mask
, uint32 val
)
2419 if (sih
->ccrev
< 16)
2422 /* gpio led powersave reg */
2424 (sih
, SI_CC_IDX
, OFFSETOF(chipcregs_t
, gpiotimeroutmask
), mask
,
2428 /* mask&set gpio timer val */
2429 uint32
si_gpiotimerval(si_t
*sih
, uint32 mask
, uint32 gpiotimerval
)
2435 if (sih
->ccrev
< 16)
2438 return si_corereg(sih
, SI_CC_IDX
,
2439 OFFSETOF(chipcregs_t
, gpiotimerval
), mask
,
2443 uint32
si_gpiopull(si_t
*sih
, bool updown
, uint32 mask
, uint32 val
)
2449 if (sih
->ccrev
< 20)
2453 (updown
? OFFSETOF(chipcregs_t
, gpiopulldown
) :
2454 OFFSETOF(chipcregs_t
, gpiopullup
));
2455 return si_corereg(sih
, SI_CC_IDX
, offs
, mask
, val
);
2458 uint32
si_gpioevent(si_t
*sih
, uint regtype
, uint32 mask
, uint32 val
)
2464 if (sih
->ccrev
< 11)
2467 if (regtype
== GPIO_REGEVT
)
2468 offs
= OFFSETOF(chipcregs_t
, gpioevent
);
2469 else if (regtype
== GPIO_REGEVT_INTMSK
)
2470 offs
= OFFSETOF(chipcregs_t
, gpioeventintmask
);
2471 else if (regtype
== GPIO_REGEVT_INTPOL
)
2472 offs
= OFFSETOF(chipcregs_t
, gpioeventintpolarity
);
2476 return si_corereg(sih
, SI_CC_IDX
, offs
, mask
, val
);
2479 void *BCMATTACHFN(si_gpio_handler_register
) (si_t
*sih
, uint32 event
,
2480 bool level
, gpio_handler_t cb
,
2489 if (sih
->ccrev
< 11)
2492 gi
= MALLOC(sii
->osh
, sizeof(gpioh_item_t
));
2496 bzero(gi
, sizeof(gpioh_item_t
));
2502 gi
->next
= sii
->gpioh_head
;
2503 sii
->gpioh_head
= gi
;
2505 return (void *)(gi
);
2508 void BCMATTACHFN(si_gpio_handler_unregister
) (si_t
*sih
, void *gpioh
)
2511 gpioh_item_t
*p
, *n
;
2514 if (sih
->ccrev
< 11)
2517 ASSERT(sii
->gpioh_head
!= NULL
);
2518 if ((void *)sii
->gpioh_head
== gpioh
) {
2519 sii
->gpioh_head
= sii
->gpioh_head
->next
;
2520 MFREE(sii
->osh
, gpioh
, sizeof(gpioh_item_t
));
2523 p
= sii
->gpioh_head
;
2526 if ((void *)n
== gpioh
) {
2528 MFREE(sii
->osh
, gpioh
, sizeof(gpioh_item_t
));
2536 ASSERT(0); /* Not found in list */
2539 void si_gpio_handler_process(si_t
*sih
)
2544 uint32 level
= si_gpioin(sih
);
2545 uint32 edge
= si_gpioevent(sih
, GPIO_REGEVT
, 0, 0);
2548 for (h
= sii
->gpioh_head
; h
!= NULL
; h
= h
->next
) {
2550 status
= (h
->level
? level
: edge
);
2552 if (status
& h
->event
)
2553 h
->handler(status
, h
->arg
);
2557 si_gpioevent(sih
, GPIO_REGEVT
, edge
, edge
); /* clear edge-trigger status */
2560 uint32
si_gpio_int_enable(si_t
*sih
, bool enable
)
2566 if (sih
->ccrev
< 11)
2569 offs
= OFFSETOF(chipcregs_t
, intmask
);
2571 (sih
, SI_CC_IDX
, offs
, CI_GPIO
, (enable
? CI_GPIO
: 0));
2574 /* Return the size of the specified SOCRAM bank */
2576 socram_banksize(si_info_t
*sii
, sbsocramregs_t
*regs
, u8 index
,
2579 uint banksize
, bankinfo
;
2580 uint bankidx
= index
| (mem_type
<< SOCRAM_BANKIDX_MEMTYPE_SHIFT
);
2582 ASSERT(mem_type
<= SOCRAM_MEMTYPE_DEVRAM
);
2584 W_REG(sii
->osh
, ®s
->bankidx
, bankidx
);
2585 bankinfo
= R_REG(sii
->osh
, ®s
->bankinfo
);
2587 SOCRAM_BANKINFO_SZBASE
* ((bankinfo
& SOCRAM_BANKINFO_SZMASK
) + 1);
2591 void si_socdevram(si_t
*sih
, bool set
, u8
*enable
, u8
*protect
)
2596 sbsocramregs_t
*regs
;
2602 /* Block ints and save current core */
2603 INTR_OFF(sii
, intr_val
);
2604 origidx
= si_coreidx(sih
);
2607 *enable
= *protect
= 0;
2609 /* Switch to SOCRAM core */
2610 regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0);
2614 /* Get info for determining size */
2615 wasup
= si_iscoreup(sih
);
2617 si_core_reset(sih
, 0, 0);
2619 corerev
= si_corerev(sih
);
2620 if (corerev
>= 10) {
2624 uint32 bankidx
, bankinfo
;
2626 extcinfo
= R_REG(sii
->osh
, ®s
->extracoreinfo
);
2627 nb
= ((extcinfo
& SOCRAM_DEVRAMBANK_MASK
) >>
2628 SOCRAM_DEVRAMBANK_SHIFT
);
2629 for (i
= 0; i
< nb
; i
++) {
2631 i
| (SOCRAM_MEMTYPE_DEVRAM
<<
2632 SOCRAM_BANKIDX_MEMTYPE_SHIFT
);
2633 W_REG(sii
->osh
, ®s
->bankidx
, bankidx
);
2634 bankinfo
= R_REG(sii
->osh
, ®s
->bankinfo
);
2636 bankinfo
&= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK
;
2637 bankinfo
&= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK
;
2641 SOCRAM_BANKINFO_DEVRAMSEL_SHIFT
);
2645 SOCRAM_BANKINFO_DEVRAMPRO_SHIFT
);
2647 W_REG(sii
->osh
, ®s
->bankinfo
, bankinfo
);
2648 } else if (i
== 0) {
2649 if (bankinfo
& SOCRAM_BANKINFO_DEVRAMSEL_MASK
) {
2652 SOCRAM_BANKINFO_DEVRAMPRO_MASK
)
2659 /* Return to previous state and core */
2661 si_core_disable(sih
, 0);
2662 si_setcoreidx(sih
, origidx
);
2665 INTR_RESTORE(sii
, intr_val
);
2668 bool si_socdevram_pkg(si_t
*sih
)
2670 if (si_socdevram_size(sih
) > 0)
2676 uint32
si_socdevram_size(si_t
*sih
)
2682 sbsocramregs_t
*regs
;
2688 /* Block ints and save current core */
2689 INTR_OFF(sii
, intr_val
);
2690 origidx
= si_coreidx(sih
);
2692 /* Switch to SOCRAM core */
2693 regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0);
2697 /* Get info for determining size */
2698 wasup
= si_iscoreup(sih
);
2700 si_core_reset(sih
, 0, 0);
2702 corerev
= si_corerev(sih
);
2703 if (corerev
>= 10) {
2708 extcinfo
= R_REG(sii
->osh
, ®s
->extracoreinfo
);
2709 nb
= (((extcinfo
& SOCRAM_DEVRAMBANK_MASK
) >>
2710 SOCRAM_DEVRAMBANK_SHIFT
));
2711 for (i
= 0; i
< nb
; i
++)
2713 socram_banksize(sii
, regs
, i
,
2714 SOCRAM_MEMTYPE_DEVRAM
);
2717 /* Return to previous state and core */
2719 si_core_disable(sih
, 0);
2720 si_setcoreidx(sih
, origidx
);
2723 INTR_RESTORE(sii
, intr_val
);
2728 /* Return the RAM size of the SOCRAM core */
2729 uint32
si_socram_size(si_t
*sih
)
2735 sbsocramregs_t
*regs
;
2743 /* Block ints and save current core */
2744 INTR_OFF(sii
, intr_val
);
2745 origidx
= si_coreidx(sih
);
2747 /* Switch to SOCRAM core */
2748 regs
= si_setcore(sih
, SOCRAM_CORE_ID
, 0);
2752 /* Get info for determining size */
2753 wasup
= si_iscoreup(sih
);
2755 si_core_reset(sih
, 0, 0);
2756 corerev
= si_corerev(sih
);
2757 coreinfo
= R_REG(sii
->osh
, ®s
->coreinfo
);
2759 /* Calculate size from coreinfo based on rev */
2761 memsize
= 1 << (16 + (coreinfo
& SRCI_MS0_MASK
));
2762 else if (corerev
< 3) {
2763 memsize
= 1 << (SR_BSZ_BASE
+ (coreinfo
& SRCI_SRBSZ_MASK
));
2764 memsize
*= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
2765 } else if ((corerev
<= 7) || (corerev
== 12)) {
2766 uint nb
= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
2767 uint bsz
= (coreinfo
& SRCI_SRBSZ_MASK
);
2768 uint lss
= (coreinfo
& SRCI_LSS_MASK
) >> SRCI_LSS_SHIFT
;
2771 memsize
= nb
* (1 << (bsz
+ SR_BSZ_BASE
));
2773 memsize
+= (1 << ((lss
- 1) + SR_BSZ_BASE
));
2776 uint nb
= (coreinfo
& SRCI_SRNB_MASK
) >> SRCI_SRNB_SHIFT
;
2777 for (i
= 0; i
< nb
; i
++)
2779 socram_banksize(sii
, regs
, i
, SOCRAM_MEMTYPE_RAM
);
2782 /* Return to previous state and core */
2784 si_core_disable(sih
, 0);
2785 si_setcoreidx(sih
, origidx
);
2788 INTR_RESTORE(sii
, intr_val
);
2793 void si_chipcontrl_epa4331(si_t
*sih
, bool on
)
2801 origidx
= si_coreidx(sih
);
2803 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
2805 val
= R_REG(sii
->osh
, &cc
->chipcontrol
);
2808 if (sih
->chippkg
== 9 || sih
->chippkg
== 0xb) {
2809 /* Ext PA Controls for 4331 12x9 Package */
2810 W_REG(sii
->osh
, &cc
->chipcontrol
, val
|
2811 (CCTRL4331_EXTPA_EN
|
2812 CCTRL4331_EXTPA_ON_GPIO2_5
));
2814 /* Ext PA Controls for 4331 12x12 Package */
2815 W_REG(sii
->osh
, &cc
->chipcontrol
,
2816 val
| (CCTRL4331_EXTPA_EN
));
2819 val
&= ~(CCTRL4331_EXTPA_EN
| CCTRL4331_EXTPA_ON_GPIO2_5
);
2820 W_REG(sii
->osh
, &cc
->chipcontrol
, val
);
2823 si_setcoreidx(sih
, origidx
);
2826 /* Enable BT-COEX & Ex-PA for 4313 */
2827 void si_epa_4313war(si_t
*sih
)
2834 origidx
= si_coreidx(sih
);
2836 cc
= (chipcregs_t
*) si_setcore(sih
, CC_CORE_ID
, 0);
2839 W_REG(sii
->osh
, &cc
->gpiocontrol
,
2840 R_REG(sii
->osh
, &cc
->gpiocontrol
) | GPIO_CTRL_EPA_EN_MASK
);
2842 si_setcoreidx(sih
, origidx
);
2845 /* check if the device is removed */
2846 bool si_deviceremoved(si_t
*sih
)
2853 switch (BUSTYPE(sih
->bustype
)) {
2855 ASSERT(sii
->osh
!= NULL
);
2856 w
= OSL_PCI_READ_CONFIG(sii
->osh
, PCI_CFG_VID
, sizeof(uint32
));
2857 if ((w
& 0xFFFF) != VENDOR_BROADCOM
)
2864 bool si_is_sprom_available(si_t
*sih
)
2866 if (sih
->ccrev
>= 31) {
2872 if ((sih
->cccaps
& CC_CAP_SROM
) == 0)
2876 origidx
= sii
->curidx
;
2877 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
2878 sromctrl
= R_REG(sii
->osh
, &cc
->sromcontrol
);
2879 si_setcoreidx(sih
, origidx
);
2880 return sromctrl
& SRC_PRESENT
;
2883 switch (CHIPID(sih
->chip
)) {
2884 case BCM4329_CHIP_ID
:
2885 return (sih
->chipst
& CST4329_SPROM_SEL
) != 0;
2886 case BCM4319_CHIP_ID
:
2887 return (sih
->chipst
& CST4319_SPROM_SEL
) != 0;
2888 case BCM4336_CHIP_ID
:
2889 return (sih
->chipst
& CST4336_SPROM_PRESENT
) != 0;
2890 case BCM4330_CHIP_ID
:
2891 return (sih
->chipst
& CST4330_SPROM_PRESENT
) != 0;
2892 case BCM4313_CHIP_ID
:
2893 return (sih
->chipst
& CST4313_SPROM_PRESENT
) != 0;
2894 case BCM4331_CHIP_ID
:
2895 return (sih
->chipst
& CST4331_SPROM_PRESENT
) != 0;
2901 bool si_is_otp_disabled(si_t
*sih
)
2903 switch (CHIPID(sih
->chip
)) {
2904 case BCM4329_CHIP_ID
:
2905 return (sih
->chipst
& CST4329_SPROM_OTP_SEL_MASK
) ==
2907 case BCM4319_CHIP_ID
:
2908 return (sih
->chipst
& CST4319_SPROM_OTP_SEL_MASK
) ==
2910 case BCM4336_CHIP_ID
:
2911 return (sih
->chipst
& CST4336_OTP_PRESENT
) == 0;
2912 case BCM4330_CHIP_ID
:
2913 return (sih
->chipst
& CST4330_OTP_PRESENT
) == 0;
2914 case BCM4313_CHIP_ID
:
2915 return (sih
->chipst
& CST4313_OTP_PRESENT
) == 0;
2916 /* These chips always have their OTP on */
2917 case BCM43224_CHIP_ID
:
2918 case BCM43225_CHIP_ID
:
2919 case BCM43421_CHIP_ID
:
2920 case BCM43235_CHIP_ID
:
2921 case BCM43236_CHIP_ID
:
2922 case BCM43238_CHIP_ID
:
2923 case BCM4331_CHIP_ID
:
2929 bool si_is_otp_powered(si_t
*sih
)
2931 if (PMUCTL_ENAB(sih
))
2932 return si_pmu_is_otp_powered(sih
, si_osh(sih
));
2936 void si_otp_power(si_t
*sih
, bool on
)
2938 if (PMUCTL_ENAB(sih
))
2939 si_pmu_otp_power(sih
, si_osh(sih
), on
);
2945 si_is_sprom_enabled(si_t
*sih
)
2947 BCMATTACHFN(si_is_sprom_enabled
) (si_t
*sih
)
2956 si_sprom_enable(si_t
*sih
, bool enable
)
2958 BCMATTACHFN(si_sprom_enable
) (si_t
*sih
, bool enable
)
2961 if (PMUCTL_ENAB(sih
))
2962 si_pmu_sprom_enable(sih
, si_osh(sih
), enable
);
2965 /* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
2966 int si_cis_source(si_t
*sih
)
2968 /* Many chips have the same mapping of their chipstatus field */
2969 static const uint cis_sel
[] = {
2970 CIS_DEFAULT
, CIS_SROM
, CIS_OTP
, CIS_SROM
};
2971 static const uint cis_43236_sel
[] = {
2972 CIS_DEFAULT
, CIS_SROM
, CIS_OTP
, CIS_OTP
};
2974 /* PCI chips use SROM format instead of CIS */
2975 if (BUSTYPE(sih
->bustype
) == PCI_BUS
)
2976 return BCME_NOTFOUND
;
2978 switch (CHIPID(sih
->chip
)) {
2979 case BCM43235_CHIP_ID
:
2980 case BCM43236_CHIP_ID
:
2981 case BCM43238_CHIP_ID
:{
2984 chipst
& CST4322_SPROM_OTP_SEL_MASK
) >>
2985 CST4322_SPROM_OTP_SEL_SHIFT
;
2987 sizeof(cis_sel
)) ? CIS_DEFAULT
:
2988 cis_43236_sel
[strap
]);
2991 case BCM4329_CHIP_ID
:
2992 return ((sih
->chipst
& CST4329_SPROM_OTP_SEL_MASK
) >=
2993 sizeof(cis_sel
)) ? CIS_DEFAULT
: cis_sel
[(sih
->
2995 CST4329_SPROM_OTP_SEL_MASK
)];
2996 case BCM4319_CHIP_ID
:{
2999 chipst
& CST4319_SPROM_OTP_SEL_MASK
) >>
3000 CST4319_SPROM_OTP_SEL_SHIFT
);
3001 return (cis_sel4319
>=
3002 sizeof(cis_sel
)) ? CIS_DEFAULT
:
3003 cis_sel
[cis_sel4319
];
3005 case BCM4336_CHIP_ID
:{
3006 if (sih
->chipst
& CST4336_SPROM_PRESENT
)
3008 if (sih
->chipst
& CST4336_OTP_PRESENT
)
3012 case BCM4330_CHIP_ID
:{
3013 if (sih
->chipst
& CST4330_SPROM_PRESENT
)
3015 if (sih
->chipst
& CST4330_OTP_PRESENT
)