aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/siutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/siutils.c')
-rw-r--r--drivers/net/wireless/bcmdhd/siutils.c626
1 files changed, 455 insertions, 171 deletions
diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c
index 0c0ffd5..2161202 100644
--- a/drivers/net/wireless/bcmdhd/siutils.c
+++ b/drivers/net/wireless/bcmdhd/siutils.c
@@ -2,7 +2,7 @@
* Misc utility routines for accessing chip-specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2014, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils.c 369572 2012-11-19 12:57:59Z $
+ * $Id: siutils.c 434466 2013-11-06 12:34:26Z $
*/
#include <bcm_cfg.h>
@@ -48,6 +48,10 @@
#include <spid.h>
#endif /* BCMSPI */
+#ifdef BCM_SDRBL
+#include <hndcpu.h>
+#endif /* BCM_SDRBL */
+
#include "siutils_priv.h"
/* local prototypes */
@@ -66,13 +70,19 @@ static uint32 si_gpioreservation = 0;
int do_4360_pcie2_war = 0;
-/*
- * Allocate a si handle.
+/* global kernel resource */
+static si_info_t ksii;
+static si_cores_info_t ksii_cores_info;
+
+/**
+ * Allocate an si handle. This function may be called multiple times.
+ *
* devid - pci device id (used to determine chip#)
* osh - opaque OS handle
* regs - virtual address of initial core registers
* bustype - pci/pcmcia/sb/sdio/etc
- * vars - pointer to a pointer area for "environment" variables
+ * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
+ * function set 'vars' to NULL, making dereferencing of this parameter undesired.
* varsz - pointer to int to return the size of the vars
*/
si_t *
@@ -80,15 +90,24 @@ si_attach(uint devid, osl_t *osh, void *regs,
uint bustype, void *sdh, char **vars, uint *varsz)
{
si_info_t *sii;
-
+ si_cores_info_t *cores_info;
/* alloc si_info_t */
- if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
+ if ((sii = MALLOCZ(osh, sizeof (si_info_t))) == NULL) {
SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
return (NULL);
}
+ /* alloc si_cores_info_t */
+ if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, sizeof (si_cores_info_t))) == NULL) {
+ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
+ MFREE(osh, sii, sizeof(si_info_t));
+ return (NULL);
+ }
+ sii->cores_info = cores_info;
+
if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
MFREE(osh, sii, sizeof(si_info_t));
+ MFREE(osh, cores_info, sizeof(si_cores_info_t));
return (NULL);
}
sii->vars = vars ? *vars : NULL;
@@ -97,30 +116,27 @@ si_attach(uint devid, osl_t *osh, void *regs,
return (si_t *)sii;
}
-/* global kernel resource */
-static si_info_t ksii;
static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
-/* generic kernel variant of si_attach() */
+/** generic kernel variant of si_attach() */
si_t *
si_kattach(osl_t *osh)
{
static bool ksii_attached = FALSE;
-
- if (!osh) {
- SI_ERROR(("%s: osh is NULL\n", __FUNCTION__));
- return NULL;
- }
+ si_cores_info_t *cores_info;
if (!ksii_attached) {
void *regs = NULL;
regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
+ cores_info = (si_cores_info_t *)&ksii_cores_info;
+ ksii.cores_info = cores_info;
+ ASSERT(osh);
if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
SI_BUS, NULL,
- osh != SI_OSH ? &ksii.vars : NULL,
- osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
+ osh != SI_OSH ? &(ksii.vars) : NULL,
+ osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) {
SI_ERROR(("si_kattach: si_doattach failed\n"));
REG_UNMAP(regs);
return NULL;
@@ -210,6 +226,7 @@ static bool
si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
uint *origidx, void *regs)
{
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
bool pci, pcie, pcie_gen2 = FALSE;
uint i;
uint pciidx, pcieidx, pcirev, pcierev;
@@ -259,9 +276,24 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
/* Display cores found */
SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
- i, cid, crev, sii->coresba[i], sii->regs[i]));
+ i, cid, crev, cores_info->coresba[i], cores_info->regs[i]));
+
+ if (BUSTYPE(bustype) == SI_BUS) {
+ /* now look at the chipstatus register to figure the pacakge */
+ /* for SDIO but downloaded on PCIE dev */
+ if (cid == PCIE2_CORE_ID) {
+ if ((CHIPID(sii->pub.chip) == BCM43602_CHIP_ID) ||
+ ((CHIPID(sii->pub.chip) == BCM4345_CHIP_ID) &&
+ CST4345_CHIPMODE_PCIE(sii->pub.chipst))) {
+ pcieidx = i;
+ pcierev = crev;
+ pcie = TRUE;
+ pcie_gen2 = TRUE;
+ }
+ }
- if (BUSTYPE(bustype) == PCI_BUS) {
+ }
+ else if (BUSTYPE(bustype) == PCI_BUS) {
if (cid == PCI_CORE_ID) {
pciidx = i;
pcirev = crev;
@@ -289,11 +321,14 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
}
/* find the core idx before entering this func. */
- if ((savewin && (savewin == sii->coresba[i])) ||
- (regs == sii->regs[i]))
+ if ((savewin && (savewin == cores_info->coresba[i])) ||
+ (regs == cores_info->regs[i]))
*origidx = i;
}
+#if defined(PCIE_FULL_DONGLE)
+ pci = FALSE;
+#endif
if (pci) {
sii->pub.buscoretype = PCI_CORE_ID;
sii->pub.buscorerev = pcirev;
@@ -333,6 +368,12 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
+/**
+ * Allocate an si handle. This function may be called multiple times.
+ *
+ * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
+ * function set 'vars' to NULL.
+ */
static si_info_t *
si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
uint bustype, void *sdh, char **vars, uint *varsz)
@@ -344,9 +385,8 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
uint origidx;
#if !defined(_CFEZ_) || defined(CFG_WL)
#endif
- ASSERT(GOODREGS(regs));
- bzero((uchar*)sii, sizeof(si_info_t));
+ ASSERT(GOODREGS(regs));
savewin = 0;
@@ -357,6 +397,13 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
sii->osh = osh;
+ /* check to see if we are a si core mimic'ing a pci core */
+ if ((bustype == PCI_BUS) &&
+ (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
+ SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
+ "devid:0x%x\n", __FUNCTION__, devid));
+ bustype = SI_BUS;
+ }
/* find Chipcommon address */
if (bustype == PCI_BUS) {
@@ -396,6 +443,7 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
return NULL;
}
w = R_REG(osh, &cc->chipid);
+ if ((w & 0xfffff) == 148277) w -= 65532;
sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
/* Might as wll fill in chip id rev & pkg */
sih->chip = w & CID_ID_MASK;
@@ -470,6 +518,26 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
}
#endif
+#ifdef BCM_SDRBL
+ /* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is
+ * not turned on, then we want to hold arm in reset.
+ * Bottomline: In sdrenable case, we allow arm to boot only when protection is
+ * turned on.
+ */
+ if (CHIP_HOSTIF_PCIE(&(sii->pub))) {
+ uint32 sflags = si_arm_sflags(&(sii->pub));
+
+ /* If SDR is enabled but protection is not turned on
+ * then we want to force arm to WFI.
+ */
+ if ((sflags & (SISF_SDRENABLE | SISF_TCMPROT)) == SISF_SDRENABLE) {
+ disable_arm_irq();
+ while (1) {
+ hnd_cpu_wait(sih);
+ }
+ }
+ }
+#endif /* BCM_SDRBL */
pvars = NULL;
BCM_REFERENCE(pvars);
@@ -497,6 +565,7 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
/* clear any previous epidiag-induced target abort */
ASSERT(!si_taclear(sih, FALSE));
+
return (sii);
exit:
@@ -504,27 +573,27 @@ exit:
return NULL;
}
-/* may be called with core in reset */
+/** may be called with core in reset */
void
si_detach(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint idx;
- sii = SI_INFO(sih);
-
- if (sii == NULL)
- return;
-
if (BUSTYPE(sih->bustype) == SI_BUS)
for (idx = 0; idx < SI_MAXCORES; idx++)
- if (sii->regs[idx]) {
- REG_UNMAP(sii->regs[idx]);
- sii->regs[idx] = NULL;
+ if (cores_info->regs[idx]) {
+ REG_UNMAP(cores_info->regs[idx]);
+ cores_info->regs[idx] = NULL;
}
+#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
+ if (cores_info != &ksii_cores_info)
+#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
+ MFREE(sii->osh, cores_info, sizeof(si_cores_info_t));
#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
if (sii != &ksii)
@@ -554,14 +623,13 @@ si_setosh(si_t *sih, osl_t *osh)
sii->osh = osh;
}
-/* register driver interrupt disabling and restoring callback functions */
+/** register driver interrupt disabling and restoring callback functions */
void
si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
void *intrsenabled_fn, void *intr_arg)
{
- si_info_t *sii;
-
- sii = SI_INFO(sih);
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
sii->intr_arg = intr_arg;
sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
@@ -569,7 +637,7 @@ si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
/* save current core id. when this function called, the current core
* must be the core which provides driver functions(il, et, wl, etc.)
*/
- sii->dev_coreid = sii->coreid[sii->curidx];
+ sii->dev_coreid = cores_info->coreid[sii->curidx];
}
void
@@ -612,6 +680,17 @@ si_flag(si_t *sih)
}
}
+uint
+si_flag_alt(si_t *sih)
+{
+ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_flag_alt(sih);
+ else {
+ ASSERT(0);
+ return 0;
+ }
+}
+
void
si_setint(si_t *sih, int siflag)
{
@@ -628,10 +707,10 @@ si_setint(si_t *sih, int siflag)
uint
si_coreid(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
- sii = SI_INFO(sih);
- return sii->coreid[sii->curidx];
+ return cores_info->coreid[sii->curidx];
}
uint
@@ -643,17 +722,17 @@ si_coreidx(si_t *sih)
return sii->curidx;
}
-/* return the core-type instantiation # of the current core */
+/** return the core-type instantiation # of the current core */
uint
si_coreunit(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint idx;
uint coreid;
uint coreunit;
uint i;
- sii = SI_INFO(sih);
coreunit = 0;
idx = sii->curidx;
@@ -663,7 +742,7 @@ si_coreunit(si_t *sih)
/* count the cores of our type */
for (i = 0; i < idx; i++)
- if (sii->coreid[i] == coreid)
+ if (cores_info->coreid[i] == coreid)
coreunit++;
return (coreunit);
@@ -705,20 +784,20 @@ si_corerev(si_t *sih)
}
}
-/* return index of coreid or BADIDX if not found */
+/** return index of coreid or BADIDX if not found */
uint
si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint found;
uint i;
- sii = SI_INFO(sih);
found = 0;
for (i = 0; i < sii->numcores; i++)
- if (sii->coreid[i] == coreid) {
+ if (cores_info->coreid[i] == coreid) {
if (found == coreunit)
return (i);
found++;
@@ -727,19 +806,49 @@ si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
return (BADIDX);
}
-/* return list of found cores */
+/** return total coreunit of coreid or zero if not found */
+uint
+si_numcoreunits(si_t *sih, uint coreid)
+{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+ uint found;
+ uint i;
+
+ found = 0;
+
+ for (i = 0; i < sii->numcores; i++)
+ if (cores_info->coreid[i] == coreid) {
+ found++;
+ }
+
+ return (found == 0? 0:found);
+}
+
+/** return list of found cores */
uint
si_corelist(si_t *sih, uint coreid[])
{
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
+
+ bcopy((uchar*)cores_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
+ return (sii->numcores);
+}
+
+/** return current wrapper mapping */
+void *
+si_wrapperregs(si_t *sih)
+{
si_info_t *sii;
sii = SI_INFO(sih);
+ ASSERT(GOODREGS(sii->curwrap));
- bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
- return (sii->numcores);
+ return (sii->curwrap);
}
-/* return current register mapping */
+/** return current register mapping */
void *
si_coreregs(si_t *sih)
{
@@ -751,7 +860,7 @@ si_coreregs(si_t *sih)
return (sii->curmap);
}
-/*
+/**
* This function changes logical "focus" to the indicated core;
* must be called with interrupts off.
* Moreover, callers should keep interrupts off during switching out of and back to d11 core
@@ -792,14 +901,13 @@ si_setcoreidx(si_t *sih, uint coreidx)
}
}
-/* Turn off interrupt as required by sb_setcore, before switch core */
+/** Turn off interrupt as required by sb_setcore, before switch core */
void *
si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
{
void *cc;
- si_info_t *sii;
-
- sii = SI_INFO(sih);
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
if (SI_FAST(sii)) {
/* Overloading the origidx variable to remember the coreid,
@@ -824,9 +932,9 @@ si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
void
si_restore_core(si_t *sih, uint coreid, uint intr_val)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
- sii = SI_INFO(sih);
if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
return;
@@ -971,6 +1079,27 @@ si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
}
}
+/*
+ * If there is no need for fiddling with interrupts or core switches (typically silicon
+ * back plane registers, pci registers and chipcommon registers), this function
+ * returns the register offset on this core to a mapped address. This address can
+ * be used for W_REG/R_REG directly.
+ *
+ * For accessing registers that would need a core switch, this function will return
+ * NULL.
+ */
+uint32 *
+si_corereg_addr(si_t *sih, uint coreidx, uint regoff)
+{
+ if (CHIPTYPE(sih->socitype) == SOCI_SB)
+ return sb_corereg_addr(sih, coreidx, regoff);
+ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
+ return ai_corereg_addr(sih, coreidx, regoff);
+ else {
+ return 0;
+ }
+}
+
void
si_core_disable(si_t *sih, uint32 bits)
{
@@ -993,7 +1122,7 @@ si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
ub_core_reset(sih, bits, resetbits);
}
-/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
+/** Run bist on current core. Caller needs to take care of core-specific bist hazards */
int
si_corebist(si_t *sih)
{
@@ -1032,7 +1161,7 @@ factor6(uint32 x)
}
}
-/* calculate the speed the SI would run at given a set of clockcontrol values */
+/** calculate the speed the SI would run at given a set of clockcontrol values */
uint32
si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
{
@@ -1116,8 +1245,80 @@ si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
}
}
+/**
+ * Some chips could have multiple host interfaces, however only one will be active.
+ * For a given chip. Depending pkgopt and cc_chipst return the active host interface.
+ */
+uint
+si_chip_hostif(si_t *sih)
+{
+ uint hosti = 0;
+
+ switch (CHIPID(sih->chip)) {
+
+ case BCM43602_CHIP_ID:
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ case BCM4360_CHIP_ID:
+ /* chippkg bit-0 == 0 is PCIE only pkgs
+ * chippkg bit-0 == 1 has both PCIE and USB cores enabled
+ */
+ if ((sih->chippkg & 0x1) && (sih->chipst & CST4360_MODE_USB))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else
+ hosti = CHIP_HOSTIF_PCIEMODE;
+
+ break;
+
+ case BCM4335_CHIP_ID:
+ /* TBD: like in 4360, do we need to check pkg? */
+ if (CST4335_CHIPMODE_USB20D(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ case BCM4345_CHIP_ID:
+ if (CST4345_CHIPMODE_USB20D(sih->chipst) || CST4345_CHIPMODE_HSIC(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4345_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else if (CST4345_CHIPMODE_PCIE(sih->chipst))
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+
+ case BCM4350_CHIP_ID:
+ case BCM4354_CHIP_ID:
+ case BCM43556_CHIP_ID:
+ case BCM43558_CHIP_ID:
+ case BCM43566_CHIP_ID:
+ case BCM43568_CHIP_ID:
+ case BCM43569_CHIP_ID:
+ if (CST4350_CHIPMODE_USB20D(sih->chipst) ||
+ CST4350_CHIPMODE_HSIC20D(sih->chipst) ||
+ CST4350_CHIPMODE_USB30D(sih->chipst) ||
+ CST4350_CHIPMODE_USB30D_WL(sih->chipst) ||
+ CST4350_CHIPMODE_HSIC30D(sih->chipst))
+ hosti = CHIP_HOSTIF_USBMODE;
+ else if (CST4350_CHIPMODE_SDIOD(sih->chipst))
+ hosti = CHIP_HOSTIF_SDIOMODE;
+ else if (CST4350_CHIPMODE_PCIE(sih->chipst))
+ hosti = CHIP_HOSTIF_PCIEMODE;
+ break;
+
+ default:
+ break;
+ }
+
+ return hosti;
+}
+
-/* set chip watchdog reset timer to fire in 'ticks' */
+/** set chip watchdog reset timer to fire in 'ticks' */
void
si_watchdog(si_t *sih, uint ticks)
{
@@ -1159,7 +1360,7 @@ si_watchdog(si_t *sih, uint ticks)
}
}
-/* trigger watchdog reset after ms milliseconds */
+/** trigger watchdog reset after ms milliseconds */
void
si_watchdog_ms(si_t *sih, uint32 ms)
{
@@ -1179,7 +1380,7 @@ si_taclear(si_t *sih, bool details)
-/* return the slow clock source - LPO, XTAL, or PCI */
+/** return the slow clock source - LPO, XTAL, or PCI */
static uint
si_slowclk_src(si_info_t *sii)
{
@@ -1196,12 +1397,13 @@ si_slowclk_src(si_info_t *sii)
return (SCC_SS_XTAL);
} else if (sii->pub.ccrev < 10) {
cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
+ ASSERT(cc);
return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
} else /* Insta-clock */
return (SCC_SS_XTAL);
}
-/* return the ILP (slowclock) min or max frequency */
+/** return the ILP (slowclock) min or max frequency */
static uint
si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
{
@@ -1266,7 +1468,7 @@ si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
}
-/* initialize power control delay registers */
+/** initialize power control delay registers */
void
si_clkctl_init(si_t *sih)
{
@@ -1302,14 +1504,14 @@ si_clkctl_init(si_t *sih)
}
-/* change logical "focus" to the gpio core for optimized access */
+/** change logical "focus" to the gpio core for optimized access */
void *
si_gpiosetcore(si_t *sih)
{
return (si_setcoreidx(sih, SI_CC_IDX));
}
-/*
+/**
* mask & set gpiocontrol bits.
* If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
* If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
@@ -1336,7 +1538,7 @@ si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
}
-/* mask&set gpio output enable bits */
+/** mask&set gpio output enable bits */
uint32
si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
{
@@ -1358,7 +1560,7 @@ si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
}
-/* mask&set gpio output bits */
+/** mask&set gpio output bits */
uint32
si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
{
@@ -1380,7 +1582,7 @@ si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
}
-/* reserve one gpio */
+/** reserve one gpio */
uint32
si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
{
@@ -1406,12 +1608,12 @@ si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
return si_gpioreservation;
}
-/* release one gpio */
-/*
+/**
+ * release one gpio.
+ *
* releasing the gpio doesn't change the current value on the GPIO last write value
- * persists till some one overwrites it
+ * persists till someone overwrites it.
*/
-
uint32
si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
{
@@ -1540,13 +1742,12 @@ void *
si_gpio_handler_register(si_t *sih, uint32 event,
bool level, gpio_handler_t cb, void *arg)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
gpioh_item_t *gi;
ASSERT(event);
ASSERT(cb != NULL);
- sii = SI_INFO(sih);
if (sih->ccrev < 11)
return NULL;
@@ -1568,10 +1769,9 @@ si_gpio_handler_register(si_t *sih, uint32 event,
void
si_gpio_handler_unregister(si_t *sih, void *gpioh)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
gpioh_item_t *p, *n;
- sii = SI_INFO(sih);
if (sih->ccrev < 11)
return;
@@ -1600,14 +1800,13 @@ si_gpio_handler_unregister(si_t *sih, void *gpioh)
void
si_gpio_handler_process(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
gpioh_item_t *h;
uint32 level = si_gpioin(sih);
uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
- sii = SI_INFO(sih);
for (h = sii->gpioh_head; h != NULL; h = h->next) {
if (h->handler) {
uint32 status = (h->level ? level : edge) & h->event;
@@ -1635,7 +1834,7 @@ si_gpio_int_enable(si_t *sih, bool enable)
}
-/* Return the size of the specified SOCRAM bank */
+/** Return the size of the specified SOCRAM bank */
static uint
socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
{
@@ -1653,15 +1852,14 @@ socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
void
si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
sbsocramregs_t *regs;
bool wasup;
uint corerev;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -1728,7 +1926,8 @@ done:
bool
si_socdevram_remap_isenb(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
sbsocramregs_t *regs;
@@ -1739,8 +1938,6 @@ si_socdevram_remap_isenb(si_t *sih)
uint8 i;
uint32 bankidx, bankinfo;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -1790,7 +1987,8 @@ si_socdevram_pkg(si_t *sih)
uint32
si_socdevram_size(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
uint32 memsize = 0;
@@ -1798,8 +1996,6 @@ si_socdevram_size(si_t *sih)
bool wasup;
uint corerev;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -1838,7 +2034,8 @@ done:
uint32
si_socdevram_remap_size(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
uint32 memsize = 0, banksz;
@@ -1850,8 +2047,6 @@ si_socdevram_remap_size(si_t *sih)
uint8 i;
uint32 bankidx, bankinfo;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -1901,11 +2096,12 @@ done:
return memsize;
}
-/* Return the RAM size of the SOCRAM core */
+/** Return the RAM size of the SOCRAM core */
uint32
si_socram_size(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
@@ -1915,8 +2111,6 @@ si_socram_size(si_t *sih)
uint32 coreinfo;
uint memsize = 0;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -1965,11 +2159,12 @@ done:
}
-/* Return the TCM-RAM size of the ARMCR4 core. */
+/** Return the TCM-RAM size of the ARMCR4 core. */
uint32
si_tcm_size(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
uint8 *regs;
@@ -1985,8 +2180,6 @@ si_tcm_size(si_t *sih)
uint32 *arm_bidx;
uint32 *arm_binfo;
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -2028,10 +2221,28 @@ done:
return memsize;
}
+bool
+si_has_flops(si_t *sih)
+{
+ uint origidx, cr4_rev;
+
+ /* Find out CR4 core revision */
+ origidx = si_coreidx(sih);
+ if (si_setcore(sih, ARMCR4_CORE_ID, 0)) {
+ cr4_rev = si_corerev(sih);
+ si_setcoreidx(sih, origidx);
+
+ if (cr4_rev == 1 || cr4_rev >= 3)
+ return TRUE;
+ }
+ return FALSE;
+}
+
uint32
si_socram_srmem_size(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
@@ -2045,8 +2256,6 @@ si_socram_srmem_size(si_t *sih)
return (32 * 1024);
}
- sii = SI_INFO(sih);
-
/* Block ints and save current core */
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -2088,13 +2297,12 @@ done:
void
si_btcgpiowar(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
uint origidx;
uint intr_val = 0;
chipcregs_t *cc;
- sii = SI_INFO(sih);
-
/* Make sure that there is ChipCommon core present &&
* UART_TX is strapped to 1
*/
@@ -2120,14 +2328,13 @@ si_btcgpiowar(si_t *sih)
void
si_chipcontrl_btshd0_4331(si_t *sih, bool on)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
+ si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
chipcregs_t *cc;
uint origidx;
uint32 val;
uint intr_val = 0;
- sii = SI_INFO(sih);
-
INTR_OFF(sii, intr_val);
origidx = si_coreidx(sih);
@@ -2155,12 +2362,10 @@ si_chipcontrl_btshd0_4331(si_t *sih, bool on)
void
si_chipcontrl_restore(si_t *sih, uint32 val)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
+ uint origidx = si_coreidx(sih);
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
W_REG(sii->osh, &cc->chipcontrol, val);
si_setcoreidx(sih, origidx);
@@ -2169,13 +2374,11 @@ si_chipcontrl_restore(si_t *sih, uint32 val)
uint32
si_chipcontrl_read(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
+ uint origidx = si_coreidx(sih);
uint32 val;
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
val = R_REG(sii->osh, &cc->chipcontrol);
si_setcoreidx(sih, origidx);
@@ -2185,16 +2388,12 @@ si_chipcontrl_read(si_t *sih)
void
si_chipcontrl_epa4331(si_t *sih, bool on)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
+ uint origidx = si_coreidx(sih);
uint32 val;
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
-
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
-
val = R_REG(sii->osh, &cc->chipcontrol);
if (on) {
@@ -2219,20 +2418,16 @@ si_chipcontrl_epa4331(si_t *sih, bool on)
si_setcoreidx(sih, origidx);
}
-/* switch muxed pins, on: SROM, off: FEMCTRL */
+/** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */
void
si_chipcontrl_srom4360(si_t *sih, bool on)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
+ uint origidx = si_coreidx(sih);
uint32 val;
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
-
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
-
val = R_REG(sii->osh, &cc->chipcontrol);
if (on) {
@@ -2291,22 +2486,19 @@ si_pll_reset(si_t *sih)
return (err);
}
-/* Enable BT-COEX & Ex-PA for 4313 */
+/** Enable BT-COEX & Ex-PA for 4313 */
void
si_epa_4313war(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
-
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
+ uint origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
/* EPA Fix */
W_REG(sii->osh, &cc->gpiocontrol,
- R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
+ R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
si_setcoreidx(sih, origidx);
}
@@ -2316,22 +2508,19 @@ si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
{
}
-/* Re-enable synth_pwrsw resource in min_res_mask for 4313 */
+/** Re-enable synth_pwrsw resource in min_res_mask for 4313 */
void
si_pmu_synth_pwrsw_4313_war(si_t *sih)
{
}
-/* WL/BT control for 4313 btcombo boards >= P250 */
+/** WL/BT control for 4313 btcombo boards >= P250 */
void
si_btcombo_p250_4313_war(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
-
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
+ uint origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
W_REG(sii->osh, &cc->gpiocontrol,
@@ -2345,12 +2534,9 @@ si_btcombo_p250_4313_war(si_t *sih)
void
si_btc_enable_chipcontrol(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
-
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
+ uint origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
@@ -2363,12 +2549,9 @@ si_btc_enable_chipcontrol(si_t *sih)
void
si_btcombo_43228_war(si_t *sih)
{
- si_info_t *sii;
+ si_info_t *sii = SI_INFO(sih);
chipcregs_t *cc;
- uint origidx;
-
- sii = SI_INFO(sih);
- origidx = si_coreidx(sih);
+ uint origidx = si_coreidx(sih);
cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
@@ -2378,19 +2561,16 @@ si_btcombo_43228_war(si_t *sih)
si_setcoreidx(sih, origidx);
}
-/* check if the device is removed */
+/** check if the device is removed */
bool
si_deviceremoved(si_t *sih)
{
uint32 w;
- si_info_t *sii;
-
- sii = SI_INFO(sih);
switch (BUSTYPE(sih->bustype)) {
case PCI_BUS:
- ASSERT(sii->osh != NULL);
- w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
+ ASSERT(SI_INFO(sih)->osh != NULL);
+ w = OSL_PCI_READ_CONFIG(SI_INFO(sih)->osh, PCI_CFG_VID, sizeof(uint32));
if ((w & 0xFFFF) != VENDOR_BROADCOM)
return TRUE;
break;
@@ -2413,6 +2593,7 @@ si_is_sprom_available(si_t *sih)
sii = SI_INFO(sih);
origidx = sii->curidx;
cc = si_setcoreidx(sih, SI_CC_IDX);
+ ASSERT(cc);
sromctrl = R_REG(sii->osh, &cc->sromcontrol);
si_setcoreidx(sih, origidx);
return (sromctrl & SRC_PRESENT);
@@ -2455,10 +2636,19 @@ si_is_sprom_available(si_t *sih)
return ((sih->chipst & CST4324_SPROM_MASK) &&
!(sih->chipst & CST4324_SFLASH_MASK));
case BCM4335_CHIP_ID:
+ case BCM4345_CHIP_ID:
return ((sih->chipst & CST4335_SPROM_MASK) &&
!(sih->chipst & CST4335_SFLASH_MASK));
case BCM4350_CHIP_ID:
+ case BCM4354_CHIP_ID:
+ case BCM43556_CHIP_ID:
+ case BCM43558_CHIP_ID:
+ case BCM43566_CHIP_ID:
+ case BCM43568_CHIP_ID:
+ case BCM43569_CHIP_ID:
return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
+ case BCM43602_CHIP_ID:
+ return (sih->chipst & CST43602_SPROM_PRESENT) != 0;
case BCM43131_CHIP_ID:
case BCM43217_CHIP_ID:
case BCM43227_CHIP_ID:
@@ -2474,12 +2664,10 @@ si_is_sprom_available(si_t *sih)
uint32 si_get_sromctl(si_t *sih)
{
chipcregs_t *cc;
- uint origidx;
+ uint origidx = si_coreidx(sih);
uint32 sromctl;
- osl_t *osh;
+ osl_t *osh = si_osh(sih);
- osh = si_osh(sih);
- origidx = si_coreidx(sih);
cc = si_setcoreidx(sih, SI_CC_IDX);
ASSERT((uintptr)cc);
@@ -2493,11 +2681,9 @@ uint32 si_get_sromctl(si_t *sih)
int si_set_sromctl(si_t *sih, uint32 value)
{
chipcregs_t *cc;
- uint origidx;
- osl_t *osh;
+ uint origidx = si_coreidx(sih);
+ osl_t *osh = si_osh(sih);
- osh = si_osh(sih);
- origidx = si_coreidx(sih);
cc = si_setcoreidx(sih, SI_CC_IDX);
ASSERT((uintptr)cc);
@@ -2529,3 +2715,101 @@ si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32
si_setcoreidx(sih, origidx);
return ret_val;
}
+
+
+/* cleanup the hndrte timer from the host when ARM is been halted
+ * without a chance for ARM cleanup its resources
+ * If left not cleanup, Intr from a software timer can still
+ * request HT clk when ARM is halted.
+ */
+uint32
+si_pmu_res_req_timer_clr(si_t *sih)
+{
+ uint32 mask;
+
+ mask = PRRT_REQ_ACTIVE | PRRT_INTEN;
+ if (CHIPID(sih->chip) != BCM4328_CHIP_ID)
+ mask <<= 14;
+ /* clear mask bits */
+ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), mask, 0);
+ /* readback to ensure write completes */
+ return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), 0, 0);
+}
+
+/** turn on/off rfldo */
+void
+si_pmu_rfldo(si_t *sih, bool on)
+{
+}
+
+#ifdef SURVIVE_PERST_ENAB
+static uint32
+si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val)
+{
+ si_info_t *sii;
+
+ sii = SI_INFO(sih);
+
+ if (!PCIE(sii))
+ return (0);
+
+ return pcie_survive_perst(sii->pch, mask, val);
+}
+
+static void
+si_watchdog_reset(si_t *sih)
+{
+ si_info_t *sii = SI_INFO(sih);
+ chipcregs_t *cc;
+ uint32 origidx, i;
+
+ origidx = si_coreidx(sih);
+ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
+ /* issue a watchdog reset */
+ W_REG(sii->osh, &cc->pmuwatchdog, 2);
+ /* do busy wait for 20ms */
+ for (i = 0; i < 2000; i++) {
+ OSL_DELAY(10);
+ }
+ si_setcoreidx(sih, origidx);
+}
+#endif /* SURVIVE_PERST_ENAB */
+
+void
+si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val)
+{
+#ifdef SURVIVE_PERST_ENAB
+ if (BUSTYPE(sih->bustype) != PCI_BUS)
+ return;
+
+ if ((CHIPID(sih->chip) != BCM4360_CHIP_ID && CHIPID(sih->chip) != BCM4352_CHIP_ID) ||
+ (CHIPREV(sih->chiprev) >= 4))
+ return;
+
+ if (reset) {
+ si_info_t *sii = SI_INFO(sih);
+ uint32 bar0win, bar0win_after;
+
+ /* save the bar0win */
+ bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+
+ si_watchdog_reset(sih);
+
+ bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
+ if (bar0win_after != bar0win) {
+ SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n",
+ __FUNCTION__, bar0win, bar0win_after));
+ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win);
+ }
+ }
+ if (sperst_mask) {
+ /* enable survive perst */
+ si_pcie_survive_perst(sih, sperst_mask, sperst_val);
+ }
+#endif /* SURVIVE_PERST_ENAB */
+}
+
+void
+si_pcie_ltr_war(si_t *sih)
+{
+}