aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c40
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h21
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c339
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/nvram.c94
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/nvram.h24
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c593
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h31
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c2
13 files changed, 607 insertions, 548 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 5681b9862023..57cddee03252 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -32,6 +32,7 @@ brcmfmac-objs += \
bcdc.o \
dhd_common.o \
dhd_linux.o \
+ nvram.o \
btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 34c993dd0602..fa35b23bbaa7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -287,6 +287,9 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
s32 retry = 0;
int ret;
+ if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+ return -ENOMEDIUM;
+
/*
* figure out how to read the register based on address range
* 0x00 ~ 0x7FF: function 0 CCCR and FBR
@@ -306,9 +309,12 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
usleep_range(1000, 2000);
ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz,
data, write);
- } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+ } while (ret != 0 && ret != -ENOMEDIUM &&
+ retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
- if (ret != 0)
+ if (ret == -ENOMEDIUM)
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+ else if (ret != 0)
brcmf_err("failed with %d\n", ret);
return ret;
@@ -320,6 +326,9 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
int err = 0, i;
u8 addr[3];
+ if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+ return -ENOMEDIUM;
+
addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
@@ -429,6 +438,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
bool write, u32 addr, struct sk_buff *pkt)
{
unsigned int req_sz;
+ int err;
brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
if (brcmf_sdiod_pm_resume_error(sdiodev))
@@ -439,18 +449,18 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
req_sz &= (uint)~3;
if (write)
- return sdio_memcpy_toio(sdiodev->func[fn], addr,
- ((u8 *)(pkt->data)),
- req_sz);
+ err = sdio_memcpy_toio(sdiodev->func[fn], addr,
+ ((u8 *)(pkt->data)), req_sz);
else if (fn == 1)
- return sdio_memcpy_fromio(sdiodev->func[fn],
- ((u8 *)(pkt->data)),
- addr, req_sz);
+ err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)),
+ addr, req_sz);
else
/* function 2 read is FIFO operation */
- return sdio_readsb(sdiodev->func[fn],
- ((u8 *)(pkt->data)), addr,
- req_sz);
+ err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
+ req_sz);
+ if (err == -ENOMEDIUM)
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+ return err;
}
/**
@@ -593,7 +603,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
- if (ret != 0) {
+ if (ret == -ENOMEDIUM) {
+ brcmf_bus_change_state(sdiodev->bus_if,
+ BRCMF_BUS_NOMEDIUM);
+ break;
+ } else if (ret != 0) {
brcmf_err("CMD53 sg block %s failed %d\n",
write ? "write" : "read", ret);
ret = -EIO;
@@ -852,8 +866,6 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
{
- sdiodev->bus_if->state = BRCMF_BUS_DOWN;
-
if (sdiodev->bus) {
brcmf_sdio_remove(sdiodev->bus);
sdiodev->bus = NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 5c12a07673fa..c4535616064e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -17,8 +17,12 @@
#ifndef _BRCMF_BUS_H_
#define _BRCMF_BUS_H_
+#include "dhd_dbg.h"
+
/* The level of bus communication with the dongle */
enum brcmf_bus_state {
+ BRCMF_BUS_UNKNOWN, /* Not determined yet */
+ BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */
BRCMF_BUS_DOWN, /* Not ready for frame transfers */
BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
BRCMF_BUS_DATA /* Ready for frame transfers */
@@ -144,6 +148,23 @@ struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
return bus->ops->gettxq(bus->dev);
}
+
+static inline bool brcmf_bus_ready(struct brcmf_bus *bus)
+{
+ return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA;
+}
+
+static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
+ enum brcmf_bus_state new_state)
+{
+ /* NOMEDIUM is permanent */
+ if (bus->state == BRCMF_BUS_NOMEDIUM)
+ return;
+
+ brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
+ bus->state = new_state;
+}
+
/*
* interface functions from common layer
*/
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index af39edae8c62..d4d966beb840 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -934,7 +934,7 @@ int brcmf_bus_start(struct device *dev)
p2p_ifp = NULL;
/* signal bus ready */
- bus_if->state = BRCMF_BUS_DATA;
+ brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA);
/* Bus is ready, do any initialization */
ret = brcmf_c_preinit_dcmds(ifp);
@@ -1029,6 +1029,8 @@ void brcmf_detach(struct device *dev)
/* stop firmware event handling */
brcmf_fweh_detach(drvr);
+ brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
+
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
if (drvr->iflist[i]) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 9c7f08a13105..3e991897d7ca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -41,6 +41,7 @@
#include <soc.h>
#include "sdio_host.h"
#include "sdio_chip.h"
+#include "nvram.h"
#define DCMD_RESP_TIMEOUT 2000 /* In milli second */
@@ -368,9 +369,7 @@ struct brcmf_sdio_hdrinfo {
/* Private data for SDIO bus interaction */
struct brcmf_sdio {
struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
- struct chip_info *ci; /* Chip info struct */
- char *vars; /* Variables (from CIS and/or other) */
- uint varsz; /* Size of variables buffer */
+ struct brcmf_chip *ci; /* Chip info struct */
u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
@@ -1083,10 +1082,6 @@ static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
/* Clear partial in any case */
bus->cur_read.len = 0;
-
- /* If we can't reach the device, signal failure */
- if (err)
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
/* return total length of buffer chain */
@@ -1683,8 +1678,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
bus->rxpending = true;
for (rd->seq_num = bus->rx_seq, rxleft = maxframes;
- !bus->rxskip && rxleft &&
- bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN;
+ !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if);
rd->seq_num++, rxleft--) {
/* Handle glomming separately */
@@ -2233,41 +2227,37 @@ static void brcmf_sdio_bus_stop(struct device *dev)
bus->watchdog_tsk = NULL;
}
- sdio_claim_host(bus->sdiodev->func[1]);
-
- /* Enable clock for device interrupts */
- brcmf_sdio_bus_sleep(bus, false, false);
+ if (bus_if->state == BRCMF_BUS_DOWN) {
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* Enable clock for device interrupts */
+ brcmf_sdio_bus_sleep(bus, false, false);
+
+ /* Disable and clear interrupts at the chip level also */
+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
+ local_hostintmask = bus->hostintmask;
+ bus->hostintmask = 0;
+
+ /* Force backplane clocks to assure F2 interrupt propagates */
+ saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ &err);
+ if (!err)
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ if (err)
+ brcmf_err("Failed to force clock for F2: err %d\n",
+ err);
- /* Disable and clear interrupts at the chip level also */
- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
- local_hostintmask = bus->hostintmask;
- bus->hostintmask = 0;
+ /* Turn off the bus (F2), free any pending packets */
+ brcmf_dbg(INTR, "disable SDIO interrupts\n");
+ sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
- /* Change our idea of bus state */
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+ /* Clear any pending interrupts now that F2 is disabled */
+ w_sdreg32(bus, local_hostintmask,
+ offsetof(struct sdpcmd_regs, intstatus));
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk = brcmf_sdiod_regrb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
+ sdio_release_host(sdiodev->func[1]);
}
- if (err)
- brcmf_err("Failed to force clock for F2: err %d\n", err);
-
- /* Turn off the bus (F2), free any pending packets */
- brcmf_dbg(INTR, "disable SDIO interrupts\n");
- sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
-
- /* Clear any pending interrupts now that F2 is disabled */
- w_sdreg32(bus, local_hostintmask,
- offsetof(struct sdpcmd_regs, intstatus));
-
- /* Turn off the backplane clock (only) */
- brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
- sdio_release_host(bus->sdiodev->func[1]);
-
/* Clear the data packet queues */
brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
@@ -2357,20 +2347,11 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
/* Check for inconsistent device control */
devctl = brcmf_sdiod_regrb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
- if (err) {
- brcmf_err("error reading DEVCTL: %d\n", err);
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- }
#endif /* DEBUG */
/* Read CSR, if clock on switch to AVAIL, else ignore */
clkctl = brcmf_sdiod_regrb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (err) {
- brcmf_err("error reading CSR: %d\n",
- err);
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- }
brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
devctl, clkctl);
@@ -2378,19 +2359,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
if (SBSDIO_HTAV(clkctl)) {
devctl = brcmf_sdiod_regrb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
- if (err) {
- brcmf_err("error reading DEVCTL: %d\n",
- err);
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- }
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
devctl, &err);
- if (err) {
- brcmf_err("error writing DEVCTL: %d\n",
- err);
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- }
bus->clkstate = CLK_AVAIL;
}
}
@@ -2525,9 +2496,8 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
txlimit -= framecnt;
}
- if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) {
+ if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) {
brcmf_err("failed backplane access over SDIO, halting operation\n");
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
atomic_set(&bus->intstatus, 0);
} else if (atomic_read(&bus->intstatus) ||
atomic_read(&bus->ipend) > 0 ||
@@ -3195,46 +3165,69 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
-static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter)
+#ifdef DEBUG
+static bool
+brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
+ u8 *ram_data, uint ram_sz)
{
- struct chip_info *ci = bus->ci;
-
- /* To enter download state, disable ARM and reset SOCRAM.
- * To exit download state, simply reset ARM (default is RAM boot).
- */
- if (enter) {
- bus->alp_only = true;
-
- brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
- } else {
- if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars,
- bus->varsz))
- return false;
+ char *ram_cmp;
+ int err;
+ bool ret = true;
+ int address;
+ int offset;
+ int len;
- /* Allow HT Clock now that the ARM is running. */
- bus->alp_only = false;
+ /* read back and verify */
+ brcmf_dbg(INFO, "Compare RAM dl & ul at 0x%08x; size=%d\n", ram_addr,
+ ram_sz);
+ ram_cmp = kmalloc(MEMBLOCK, GFP_KERNEL);
+ /* do not proceed while no memory but */
+ if (!ram_cmp)
+ return true;
- bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
+ address = ram_addr;
+ offset = 0;
+ while (offset < ram_sz) {
+ len = ((offset + MEMBLOCK) < ram_sz) ? MEMBLOCK :
+ ram_sz - offset;
+ err = brcmf_sdiod_ramrw(sdiodev, false, address, ram_cmp, len);
+ if (err) {
+ brcmf_err("error %d on reading %d membytes at 0x%08x\n",
+ err, len, address);
+ ret = false;
+ break;
+ } else if (memcmp(ram_cmp, &ram_data[offset], len)) {
+ brcmf_err("Downloaded RAM image is corrupted, block offset is %d, len is %d\n",
+ offset, len);
+ ret = false;
+ break;
+ }
+ offset += len;
+ address += len;
}
+ kfree(ram_cmp);
+
+ return ret;
+}
+#else /* DEBUG */
+static bool
+brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
+ u8 *ram_data, uint ram_sz)
+{
return true;
}
+#endif /* DEBUG */
-static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
+ const struct firmware *fw)
{
- const struct firmware *fw;
int err;
int offset;
int address;
int len;
- fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
- if (fw == NULL)
- return -ENOENT;
-
- if (brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4) !=
- BRCMF_MAX_CORENUM)
- memcpy(&bus->ci->rst_vec, fw->data, sizeof(bus->ci->rst_vec));
+ brcmf_dbg(TRACE, "Enter\n");
err = 0;
offset = 0;
@@ -3247,138 +3240,96 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
if (err) {
brcmf_err("error %d on writing %d membytes at 0x%08x\n",
err, len, address);
- goto failure;
+ return err;
}
offset += len;
address += len;
}
-
-failure:
- release_firmware(fw);
+ if (!err)
+ if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
+ (u8 *)fw->data, fw->size))
+ err = -EIO;
return err;
}
-/*
- * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
- * and ending in a NUL.
- * Removes carriage returns, empty lines, comment lines, and converts
- * newlines to NULs.
- * Shortens buffer as needed and pads with NULs. End of buffer is marked
- * by two NULs.
-*/
-
-static int brcmf_sdio_strip_nvram(struct brcmf_sdio *bus,
- const struct firmware *nv)
+static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
+ const struct firmware *nv)
{
- char *varbuf;
- char *dp;
- bool findNewline;
- int column;
- int ret = 0;
- uint buf_len, n, len;
-
- len = nv->size;
- varbuf = vmalloc(len);
- if (!varbuf)
- return -ENOMEM;
-
- memcpy(varbuf, nv->data, len);
- dp = varbuf;
-
- findNewline = false;
- column = 0;
-
- for (n = 0; n < len; n++) {
- if (varbuf[n] == 0)
- break;
- if (varbuf[n] == '\r')
- continue;
- if (findNewline && varbuf[n] != '\n')
- continue;
- findNewline = false;
- if (varbuf[n] == '#') {
- findNewline = true;
- continue;
- }
- if (varbuf[n] == '\n') {
- if (column == 0)
- continue;
- *dp++ = 0;
- column = 0;
- continue;
- }
- *dp++ = varbuf[n];
- column++;
- }
- buf_len = dp - varbuf;
- while (dp < varbuf + n)
- *dp++ = 0;
-
- kfree(bus->vars);
- /* roundup needed for download to device */
- bus->varsz = roundup(buf_len + 1, 4);
- bus->vars = kmalloc(bus->varsz, GFP_KERNEL);
- if (bus->vars == NULL) {
- bus->varsz = 0;
- ret = -ENOMEM;
- goto err;
- }
+ void *vars;
+ u32 varsz;
+ int address;
+ int err;
- /* copy the processed variables and add null termination */
- memcpy(bus->vars, varbuf, buf_len);
- bus->vars[buf_len] = 0;
-err:
- vfree(varbuf);
- return ret;
-}
+ brcmf_dbg(TRACE, "Enter\n");
-static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
-{
- const struct firmware *nv;
- int ret;
+ vars = brcmf_nvram_strip(nv, &varsz);
- nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
- if (nv == NULL)
- return -ENOENT;
+ if (vars == NULL)
+ return -EINVAL;
- ret = brcmf_sdio_strip_nvram(bus, nv);
+ address = bus->ci->ramsize - varsz + bus->ci->rambase;
+ err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, vars, varsz);
+ if (err)
+ brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
+ err, varsz, address);
+ else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, vars, varsz))
+ err = -EIO;
- release_firmware(nv);
+ brcmf_nvram_free(vars);
- return ret;
+ return err;
}
static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
{
int bcmerror = -EFAULT;
-
+ const struct firmware *fw;
+ u32 rstvec;
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
/* Keep arm in reset */
- if (!brcmf_sdio_download_state(bus, true)) {
- brcmf_err("error placing ARM core in reset\n");
+ brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
+
+ fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
+ if (fw == NULL) {
+ bcmerror = -ENOENT;
goto err;
}
- if (brcmf_sdio_download_code_file(bus)) {
+ rstvec = get_unaligned_le32(fw->data);
+ brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
+
+ bcmerror = brcmf_sdio_download_code_file(bus, fw);
+ release_firmware(fw);
+ if (bcmerror) {
brcmf_err("dongle image file download failed\n");
goto err;
}
- if (brcmf_sdio_download_nvram(bus)) {
+ fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
+ if (fw == NULL) {
+ bcmerror = -ENOENT;
+ goto err;
+ }
+
+ bcmerror = brcmf_sdio_download_nvram(bus, fw);
+ release_firmware(fw);
+ if (bcmerror) {
brcmf_err("dongle nvram file download failed\n");
goto err;
}
/* Take arm out of reset */
- if (!brcmf_sdio_download_state(bus, false)) {
+ if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) {
brcmf_err("error getting out of ARM core reset\n");
goto err;
}
+ /* Allow HT Clock now that the ARM is running. */
+ brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD);
bcmerror = 0;
err:
@@ -3567,9 +3518,11 @@ static int brcmf_sdio_bus_init(struct device *dev)
/* try to download image and nvram to the dongle */
if (bus_if->state == BRCMF_BUS_DOWN) {
+ bus->alp_only = true;
err = brcmf_sdio_download_firmware(bus);
if (err)
return err;
+ bus->alp_only = false;
}
if (!bus->sdiodev->bus_if->drvr)
@@ -3653,7 +3606,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
return;
}
- if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
+ if (!brcmf_bus_ready(bus->sdiodev->bus_if)) {
brcmf_err("bus is down. we have nothing to do\n");
return;
}
@@ -3664,7 +3617,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
else
if (brcmf_sdio_intr_rstatus(bus)) {
brcmf_err("failed backplane access\n");
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
/* Disable additional interrupts (is this needed now)? */
@@ -3779,8 +3731,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
u32 reg_val;
u32 drivestrength;
- bus->alp_only = true;
-
sdio_claim_host(bus->sdiodev->func[1]);
pr_debug("F1 signature read @0x18000000=0x%4x\n",
@@ -3803,6 +3753,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
goto fail;
}
+ /* SDIO register access works so moving
+ * state from UNKNOWN to DOWN.
+ */
+ brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
+
if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) {
brcmf_err("brcmf_sdio_chip_attach failed!\n");
goto fail;
@@ -4026,7 +3981,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
/* Disable F2 to clear any intermediate frame state on the dongle */
sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
- bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
bus->rxflow = false;
/* Done with backplane-dependent accesses, can drop clock... */
@@ -4082,17 +4036,26 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
}
if (bus->ci) {
- sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
- sdio_release_host(bus->sdiodev->func[1]);
+ if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
+ sdio_claim_host(bus->sdiodev->func[1]);
+ brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+ /* Leave the device in state where it is
+ * 'quiet'. This is done by putting it in
+ * download_state which essentially resets
+ * all necessary cores.
+ */
+ msleep(20);
+ brcmf_sdio_chip_enter_download(bus->sdiodev,
+ bus->ci);
+ brcmf_sdio_clkctl(bus, CLK_NONE, false);
+ sdio_release_host(bus->sdiodev->func[1]);
+ }
brcmf_sdio_chip_detach(&bus->ci);
}
brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
kfree(bus->rxbuf);
kfree(bus->hdrbuf);
- kfree(bus->vars);
kfree(bus);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c
new file mode 100644
index 000000000000..d5ef86db631b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "nvram.h"
+
+/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file
+ * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
+ * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
+ * End of buffer is completed with token identifying length of buffer.
+ */
+void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length)
+{
+ u8 *nvram;
+ u32 i;
+ u32 len;
+ u32 column;
+ u8 val;
+ bool comment;
+ u32 token;
+ __le32 token_le;
+
+ /* Alloc for extra 0 byte + roundup by 4 + length field */
+ nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL);
+ if (!nvram)
+ return NULL;
+
+ len = 0;
+ column = 0;
+ comment = false;
+ for (i = 0; i < nv->size; i++) {
+ val = nv->data[i];
+ if (val == 0)
+ break;
+ if (val == '\r')
+ continue;
+ if (comment && (val != '\n'))
+ continue;
+ comment = false;
+ if (val == '#') {
+ comment = true;
+ continue;
+ }
+ if (val == '\n') {
+ if (column == 0)
+ continue;
+ nvram[len] = 0;
+ len++;
+ column = 0;
+ continue;
+ }
+ nvram[len] = val;
+ len++;
+ column++;
+ }
+ column = len;
+ *new_length = roundup(len + 1, 4);
+ while (column != *new_length) {
+ nvram[column] = 0;
+ column++;
+ }
+
+ token = *new_length / 4;
+ token = (~token << 16) | (token & 0x0000FFFF);
+ token_le = cpu_to_le32(token);
+
+ memcpy(&nvram[*new_length], &token_le, sizeof(token_le));
+ *new_length += sizeof(token_le);
+
+ return nvram;
+}
+
+void brcmf_nvram_free(void *nvram)
+{
+ kfree(nvram);
+}
+
+
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.h b/drivers/net/wireless/brcm80211/brcmfmac/nvram.h
new file mode 100644
index 000000000000..d454580928c9
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/nvram.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_NVRAM_H
+#define BRCMFMAC_NVRAM_H
+
+
+void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length);
+void brcmf_nvram_free(void *nvram);
+
+
+#endif /* BRCMFMAC_NVRAM_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index 9fd40675f18e..82bf3c5d3cdc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -51,6 +51,9 @@
#define BCM43143_CORE_ARM_BASE 0x18003000
#define BCM43143_RAMSIZE 0x70000
+/* All D11 cores, ID 0x812 */
+#define BCM43xx_CORE_D11_BASE 0x18001000
+
#define SBCOREREV(sbidh) \
((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
((sbidh) & SSB_IDHIGH_RCLO))
@@ -66,6 +69,10 @@
/* ARM CR4 core specific control flag bits */
#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
+/* D11 core specific control flag bits */
+#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
+#define D11_BCMA_IOCTL_PHYRESET 0x0008
+
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
@@ -111,7 +118,7 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
};
u8
-brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
+brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid)
{
u8 idx;
@@ -124,7 +131,7 @@ brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
static u32
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct brcmf_chip *ci, u16 coreid)
{
u32 regdata;
u8 idx;
@@ -139,7 +146,7 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
static u32
brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct brcmf_chip *ci, u16 coreid)
{
u8 idx;
@@ -150,7 +157,7 @@ brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct brcmf_chip *ci, u16 coreid)
{
u32 regdata;
u8 idx;
@@ -169,7 +176,7 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
static bool
brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct brcmf_chip *ci, u16 coreid)
{
u32 regdata;
u8 idx;
@@ -193,7 +200,8 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits)
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits)
{
u32 regdata, base;
u8 idx;
@@ -279,52 +287,48 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits)
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits)
{
u8 idx;
u32 regdata;
+ u32 wrapbase;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
if (idx == BRCMF_MAX_CORENUM)
return;
+ wrapbase = ci->c_inf[idx].wrapbase;
+
/* if core is already in reset, just return */
- regdata = brcmf_sdiod_regrl(sdiodev,
- ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
- NULL);
+ regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
return;
- /* ensure no pending backplane operation
- * 300uc should be sufficient for backplane ops to be finish
- * extra 10ms is taken into account for firmware load stage
- * after 10300us carry on disabling the core anyway
- */
- SPINWAIT(brcmf_sdiod_regrl(sdiodev,
- ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
- NULL), 10300);
- regdata = brcmf_sdiod_regrl(sdiodev,
- ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
- NULL);
- if (regdata)
- brcmf_err("disabling core 0x%x with reset status %x\n",
- coreid, regdata);
+ /* configure reset */
+ brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
+ BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
+ regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
- brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+ /* put in reset */
+ brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
BCMA_RESET_CTL_RESET, NULL);
- udelay(1);
-
- brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- core_bits, NULL);
- regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- NULL);
usleep_range(10, 20);
+ /* wait till reset is 1 */
+ SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
+ BCMA_RESET_CTL_RESET, 300);
+
+ /* post reset configure */
+ brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
+ BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
+ regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
}
static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits)
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits, u32 post_resetbits)
{
u32 regdata;
u8 idx;
@@ -337,7 +341,8 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
- brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
+ brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits,
+ in_resetbits);
/*
* Now do the initialization sequence.
@@ -390,40 +395,37 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits)
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits, u32 post_resetbits)
{
u8 idx;
u32 regdata;
+ u32 wrapbase;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
if (idx == BRCMF_MAX_CORENUM)
return;
+ wrapbase = ci->c_inf[idx].wrapbase;
+
/* must disable first to work for arbitrary current core state */
- brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
+ brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits,
+ in_resetbits);
- /* now do initialization sequence */
- brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
- regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- NULL);
- brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
- 0, NULL);
- regdata = brcmf_sdiod_regrl(sdiodev,
- ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
- NULL);
- udelay(1);
+ while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) &
+ BCMA_RESET_CTL_RESET) {
+ brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL);
+ usleep_range(40, 60);
+ }
- brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- core_bits | BCMA_IOCTL_CLK, NULL);
- regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- NULL);
- udelay(1);
+ brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits |
+ BCMA_IOCTL_CLK, NULL);
+ regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
}
#ifdef DEBUG
/* safety check for chipinfo */
-static int brcmf_sdio_chip_cichk(struct chip_info *ci)
+static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
{
u8 core_idx;
@@ -450,189 +452,213 @@ static int brcmf_sdio_chip_cichk(struct chip_info *ci)
return 0;
}
#else /* DEBUG */
-static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
+static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
{
return 0;
}
#endif
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci)
+ struct brcmf_chip *ci)
{
u32 regdata;
- int ret;
+ u32 socitype;
/* Get CC core rev
- * Chipid is assume to be at offset 0 from regs arg
+ * Chipid is assume to be at offset 0 from SI_ENUM_BASE
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
*/
- ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
- ci->c_inf[0].base = SI_ENUM_BASE;
regdata = brcmf_sdiod_regrl(sdiodev,
- CORE_CC_REG(ci->c_inf[0].base, chipid),
+ CORE_CC_REG(SI_ENUM_BASE, chipid),
NULL);
ci->chip = regdata & CID_ID_MASK;
ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
ci->chiprev >= 2)
ci->chip = BCM4339_CHIP_ID;
- ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
+ socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
- brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
+ brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n",
+ socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev);
- /* Address of cores for new chips should be added here */
- switch (ci->chip) {
- case BCM43143_CHIP_ID:
- ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
- ci->c_inf[0].cib = 0x2b000000;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
- ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
- ci->c_inf[1].cib = 0x18000000;
- ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
- ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
- ci->c_inf[2].cib = 0x14000000;
- ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
- ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
- ci->c_inf[3].cib = 0x07000000;
- ci->ramsize = BCM43143_RAMSIZE;
- break;
- case BCM43241_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x2a084411;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18002000;
- ci->c_inf[1].wrapbase = 0x18102000;
- ci->c_inf[1].cib = 0x0e004211;
- ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- ci->c_inf[2].base = 0x18004000;
- ci->c_inf[2].wrapbase = 0x18104000;
- ci->c_inf[2].cib = 0x14080401;
- ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- ci->c_inf[3].base = 0x18003000;
- ci->c_inf[3].wrapbase = 0x18103000;
- ci->c_inf[3].cib = 0x07004211;
- ci->ramsize = 0x90000;
- break;
- case BCM4329_CHIP_ID:
+ if (socitype == SOCI_SB) {
+ if (ci->chip != BCM4329_CHIP_ID) {
+ brcmf_err("SB chip is not supported\n");
+ return -ENODEV;
+ }
+ ci->iscoreup = brcmf_sdio_sb_iscoreup;
+ ci->corerev = brcmf_sdio_sb_corerev;
+ ci->coredisable = brcmf_sdio_sb_coredisable;
+ ci->resetcore = brcmf_sdio_sb_resetcore;
+
+ ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
+ ci->c_inf[0].base = SI_ENUM_BASE;
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
ci->ramsize = BCM4329_RAMSIZE;
- break;
- case BCM4330_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x27004211;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18002000;
- ci->c_inf[1].wrapbase = 0x18102000;
- ci->c_inf[1].cib = 0x07004211;
- ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- ci->c_inf[2].base = 0x18004000;
- ci->c_inf[2].wrapbase = 0x18104000;
- ci->c_inf[2].cib = 0x0d080401;
- ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- ci->c_inf[3].base = 0x18003000;
- ci->c_inf[3].wrapbase = 0x18103000;
- ci->c_inf[3].cib = 0x03004211;
- ci->ramsize = 0x48000;
- break;
- case BCM4334_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x29004211;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18002000;
- ci->c_inf[1].wrapbase = 0x18102000;
- ci->c_inf[1].cib = 0x0d004211;
- ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- ci->c_inf[2].base = 0x18004000;
- ci->c_inf[2].wrapbase = 0x18104000;
- ci->c_inf[2].cib = 0x13080401;
- ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- ci->c_inf[3].base = 0x18003000;
- ci->c_inf[3].wrapbase = 0x18103000;
- ci->c_inf[3].cib = 0x07004211;
- ci->ramsize = 0x80000;
- break;
- case BCM4335_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x2b084411;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18005000;
- ci->c_inf[1].wrapbase = 0x18105000;
- ci->c_inf[1].cib = 0x0f004211;
- ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
- ci->c_inf[2].base = 0x18002000;
- ci->c_inf[2].wrapbase = 0x18102000;
- ci->c_inf[2].cib = 0x01084411;
- ci->ramsize = 0xc0000;
- ci->rambase = 0x180000;
- break;
- case BCM4339_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x2e084411;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18005000;
- ci->c_inf[1].wrapbase = 0x18105000;
- ci->c_inf[1].cib = 0x15004211;
- ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
- ci->c_inf[2].base = 0x18002000;
- ci->c_inf[2].wrapbase = 0x18102000;
- ci->c_inf[2].cib = 0x04084411;
- ci->ramsize = 0xc0000;
- ci->rambase = 0x180000;
- break;
- case BCM43362_CHIP_ID:
- ci->c_inf[0].wrapbase = 0x18100000;
- ci->c_inf[0].cib = 0x27004211;
- ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
- ci->c_inf[1].base = 0x18002000;
- ci->c_inf[1].wrapbase = 0x18102000;
- ci->c_inf[1].cib = 0x0a004211;
- ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
- ci->c_inf[2].base = 0x18004000;
- ci->c_inf[2].wrapbase = 0x18104000;
- ci->c_inf[2].cib = 0x08080401;
- ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
- ci->c_inf[3].base = 0x18003000;
- ci->c_inf[3].wrapbase = 0x18103000;
- ci->c_inf[3].cib = 0x03004211;
- ci->ramsize = 0x3C000;
- break;
- default:
- brcmf_err("chipid 0x%x is not supported\n", ci->chip);
- return -ENODEV;
- }
-
- ret = brcmf_sdio_chip_cichk(ci);
- if (ret)
- return ret;
-
- switch (ci->socitype) {
- case SOCI_SB:
- ci->iscoreup = brcmf_sdio_sb_iscoreup;
- ci->corerev = brcmf_sdio_sb_corerev;
- ci->coredisable = brcmf_sdio_sb_coredisable;
- ci->resetcore = brcmf_sdio_sb_resetcore;
- break;
- case SOCI_AI:
+ } else if (socitype == SOCI_AI) {
ci->iscoreup = brcmf_sdio_ai_iscoreup;
ci->corerev = brcmf_sdio_ai_corerev;
ci->coredisable = brcmf_sdio_ai_coredisable;
ci->resetcore = brcmf_sdio_ai_resetcore;
- break;
- default:
- brcmf_err("socitype %u not supported\n", ci->socitype);
+
+ ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
+ ci->c_inf[0].base = SI_ENUM_BASE;
+
+ /* Address of cores for new chips should be added here */
+ switch (ci->chip) {
+ case BCM43143_CHIP_ID:
+ ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
+ ci->c_inf[0].cib = 0x2b000000;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
+ ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
+ ci->c_inf[1].cib = 0x18000000;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
+ ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
+ ci->c_inf[2].cib = 0x14000000;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
+ ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
+ ci->c_inf[3].cib = 0x07000000;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
+ ci->ramsize = BCM43143_RAMSIZE;
+ break;
+ case BCM43241_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x2a084411;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18002000;
+ ci->c_inf[1].wrapbase = 0x18102000;
+ ci->c_inf[1].cib = 0x0e004211;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = 0x18004000;
+ ci->c_inf[2].wrapbase = 0x18104000;
+ ci->c_inf[2].cib = 0x14080401;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = 0x18003000;
+ ci->c_inf[3].wrapbase = 0x18103000;
+ ci->c_inf[3].cib = 0x07004211;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
+ ci->ramsize = 0x90000;
+ break;
+ case BCM4330_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x27004211;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18002000;
+ ci->c_inf[1].wrapbase = 0x18102000;
+ ci->c_inf[1].cib = 0x07004211;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = 0x18004000;
+ ci->c_inf[2].wrapbase = 0x18104000;
+ ci->c_inf[2].cib = 0x0d080401;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = 0x18003000;
+ ci->c_inf[3].wrapbase = 0x18103000;
+ ci->c_inf[3].cib = 0x03004211;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
+ ci->ramsize = 0x48000;
+ break;
+ case BCM4334_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x29004211;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18002000;
+ ci->c_inf[1].wrapbase = 0x18102000;
+ ci->c_inf[1].cib = 0x0d004211;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = 0x18004000;
+ ci->c_inf[2].wrapbase = 0x18104000;
+ ci->c_inf[2].cib = 0x13080401;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = 0x18003000;
+ ci->c_inf[3].wrapbase = 0x18103000;
+ ci->c_inf[3].cib = 0x07004211;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
+ ci->ramsize = 0x80000;
+ break;
+ case BCM4335_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x2b084411;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18005000;
+ ci->c_inf[1].wrapbase = 0x18105000;
+ ci->c_inf[1].cib = 0x0f004211;
+ ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
+ ci->c_inf[2].base = 0x18002000;
+ ci->c_inf[2].wrapbase = 0x18102000;
+ ci->c_inf[2].cib = 0x01084411;
+ ci->c_inf[3].id = BCMA_CORE_80211;
+ ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
+ ci->ramsize = 0xc0000;
+ ci->rambase = 0x180000;
+ break;
+ case BCM43362_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x27004211;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18002000;
+ ci->c_inf[1].wrapbase = 0x18102000;
+ ci->c_inf[1].cib = 0x0a004211;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = 0x18004000;
+ ci->c_inf[2].wrapbase = 0x18104000;
+ ci->c_inf[2].cib = 0x08080401;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = 0x18003000;
+ ci->c_inf[3].wrapbase = 0x18103000;
+ ci->c_inf[3].cib = 0x03004211;
+ ci->c_inf[4].id = BCMA_CORE_80211;
+ ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
+ ci->ramsize = 0x3C000;
+ break;
+ case BCM4339_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x2e084411;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18005000;
+ ci->c_inf[1].wrapbase = 0x18105000;
+ ci->c_inf[1].cib = 0x15004211;
+ ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
+ ci->c_inf[2].base = 0x18002000;
+ ci->c_inf[2].wrapbase = 0x18102000;
+ ci->c_inf[2].cib = 0x04084411;
+ ci->c_inf[3].id = BCMA_CORE_80211;
+ ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
+ ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
+ ci->ramsize = 0xc0000;
+ ci->rambase = 0x180000;
+ break;
+ default:
+ brcmf_err("AXI chip is not supported\n");
+ return -ENODEV;
+ }
+ } else {
+ brcmf_err("chip backplane type %u is not supported\n",
+ socitype);
return -ENODEV;
}
- return 0;
+ return brcmf_sdio_chip_cichk(ci);
}
static int
@@ -682,7 +708,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci)
+ struct brcmf_chip *ci)
{
u32 base = ci->c_inf[0].base;
@@ -713,19 +739,18 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
- ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
}
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
- struct chip_info **ci_ptr)
+ struct brcmf_chip **ci_ptr)
{
int ret;
- struct chip_info *ci;
+ struct brcmf_chip *ci;
brcmf_dbg(TRACE, "Enter\n");
- /* alloc chip_info_t */
- ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
+ ci = kzalloc(sizeof(*ci), GFP_ATOMIC);
if (!ci)
return -ENOMEM;
@@ -753,7 +778,7 @@ err:
}
void
-brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
+brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr)
{
brcmf_dbg(TRACE, "Enter\n");
@@ -772,7 +797,7 @@ static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u32 drivestrength)
+ struct brcmf_chip *ci, u32 drivestrength)
{
const struct sdiod_drive_str *str_tab = NULL;
u32 str_mask;
@@ -842,107 +867,19 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
}
}
-#ifdef DEBUG
-static bool
-brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
- char *nvram_dat, uint nvram_sz)
-{
- char *nvram_ularray;
- int err;
- bool ret = true;
-
- /* read back and verify */
- brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
- nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
- /* do not proceed while no memory but */
- if (!nvram_ularray)
- return true;
-
- /* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, nvram_sz);
-
- /* Read the vars list to temp buffer for comparison */
- err = brcmf_sdiod_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
- nvram_sz);
- if (err) {
- brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
- err, nvram_sz, nvram_addr);
- } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
- brcmf_err("Downloaded NVRAM image is corrupted\n");
- ret = false;
- }
- kfree(nvram_ularray);
-
- return ret;
-}
-#else /* DEBUG */
-static inline bool
-brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
- char *nvram_dat, uint nvram_sz)
-{
- return true;
-}
-#endif /* DEBUG */
-
-static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci,
- char *nvram_dat, uint nvram_sz)
-{
- int err;
- u32 nvram_addr;
- u32 token;
- __le32 token_le;
-
- nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
-
- /* Write the vars list */
- err = brcmf_sdiod_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
- if (err) {
- brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
- err, nvram_sz, nvram_addr);
- return false;
- }
-
- if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
- nvram_dat, nvram_sz))
- return false;
-
- /* generate token:
- * nvram size, converted to words, in lower 16-bits, checksum
- * in upper 16-bits.
- */
- token = nvram_sz / 4;
- token = (~token << 16) | (token & 0x0000FFFF);
- token_le = cpu_to_le32(token);
-
- brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
- brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
- nvram_addr, nvram_sz, token);
-
- /* Write the length token to the last word */
- if (brcmf_sdiod_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
- (u8 *)&token_le, 4))
- return false;
-
- return true;
-}
-
static void
brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci)
+ struct brcmf_chip *ci)
{
- u32 zeros = 0;
-
- ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
- ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
-
- /* clear length token */
- brcmf_sdiod_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
+ D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
+ D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0);
}
-static bool
-brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
- char *nvram_dat, uint nvram_sz)
+static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev,
+ struct brcmf_chip *ci)
{
u8 core_idx;
u32 reg_addr;
@@ -952,38 +889,45 @@ brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
return false;
}
- if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
- return false;
-
/* clear all interrupts */
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
reg_addr = ci->c_inf[core_idx].base;
reg_addr += offsetof(struct sdpcmd_regs, intstatus);
brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
- ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0);
return true;
}
static inline void
brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci)
+ struct brcmf_chip *ci)
{
- ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
- ARMCR4_BCMA_IOCTL_CPUHALT);
+ u8 idx;
+ u32 regdata;
+ u32 wrapbase;
+ idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
+
+ if (idx == BRCMF_MAX_CORENUM)
+ return;
+
+ wrapbase = ci->c_inf[idx].wrapbase;
+ regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
+ regdata &= ARMCR4_BCMA_IOCTL_CPUHALT;
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata,
+ ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
+ D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
+ D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
}
-static bool
-brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
- char *nvram_dat, uint nvram_sz)
+static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev,
+ struct brcmf_chip *ci, u32 rstvec)
{
u8 core_idx;
u32 reg_addr;
- if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
- return false;
-
/* clear all interrupts */
core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
reg_addr = ci->c_inf[core_idx].base;
@@ -991,17 +935,18 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
/* Write reset vector to address 0 */
- brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
- sizeof(ci->rst_vec));
+ brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
+ sizeof(rstvec));
/* restore ARM */
- ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
+ 0, 0);
return true;
}
void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci)
+ struct brcmf_chip *ci)
{
u8 arm_core_idx;
@@ -1015,15 +960,13 @@ void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
}
bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, char *nvram_dat,
- uint nvram_sz)
+ struct brcmf_chip *ci, u32 rstvec)
{
u8 arm_core_idx;
arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
if (BRCMF_MAX_CORENUM != arm_core_idx)
- return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
- nvram_sz);
+ return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
- return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
+ return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index 7ea424e20773..fb0614329ede 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -54,7 +54,7 @@
#define BRCMF_MAX_CORENUM 6
-struct chip_core_info {
+struct brcmf_core {
u16 id;
u16 rev;
u32 base;
@@ -63,27 +63,28 @@ struct chip_core_info {
u32 cib;
};
-struct chip_info {
+struct brcmf_chip {
u32 chip;
u32 chiprev;
- u32 socitype;
/* core info */
/* always put chipcommon core at 0, bus core at 1 */
- struct chip_core_info c_inf[BRCMF_MAX_CORENUM];
+ struct brcmf_core c_inf[BRCMF_MAX_CORENUM];
u32 pmurev;
u32 pmucaps;
u32 ramsize;
u32 rambase;
u32 rst_vec; /* reset vertor for ARM CR4 core */
- bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
u16 coreid);
- u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct brcmf_chip *ci,
u16 coreid);
void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits);
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits);
void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid, u32 core_bits);
+ struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
+ u32 in_resetbits, u32 post_resetbits);
};
struct sbconfig {
@@ -216,15 +217,15 @@ struct sdpcmd_regs {
};
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
- struct chip_info **ci_ptr);
-void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
+ struct brcmf_chip **ci_ptr);
+void brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr);
void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u32 drivestrength);
-u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
+ struct brcmf_chip *ci,
+ u32 drivestrength);
+u8 brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid);
void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci);
+ struct brcmf_chip *ci);
bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, char *nvram_dat,
- uint nvram_sz);
+ struct brcmf_chip *ci, u32 rstvec);
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index c345c32eb631..24f65cd53859 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -522,10 +522,10 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
/* update state of upper layer */
if (state == BRCMFMAC_USB_STATE_DOWN) {
brcmf_dbg(USB, "DBUS is down\n");
- bcmf_bus->state = BRCMF_BUS_DOWN;
+ brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);
} else if (state == BRCMFMAC_USB_STATE_UP) {
brcmf_dbg(USB, "DBUS is up\n");
- bcmf_bus->state = BRCMF_BUS_DATA;
+ brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA);
} else {
brcmf_dbg(USB, "DBUS current state=%d\n", state);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index aad83aef7d93..d7718a5fa2f0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -2989,6 +2989,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
}
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+ cfg->escan_info.run = brcmf_run_escan;
err = brcmf_do_escan(cfg, wiphy, ifp, request);
if (err) {
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index e71ce8c842a2..925034b80e9c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1071,7 +1071,6 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
hw->max_rates = 2; /* Primary rate and 1 fallback rate */
/* channel change time is dependent on chip and band */
- hw->channel_change_time = 7 * 1000;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_ADHOC);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 8138f1cff4e5..9417cb5a2553 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7108,7 +7108,6 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
struct sk_buff *p,
struct ieee80211_rx_status *rx_status)
{
- int preamble;
int channel;
u32 rspec;
unsigned char *plcp;
@@ -7191,7 +7190,6 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET;
/* Determine short preamble and rate_idx */
- preamble = 0;
if (is_cck_rate(rspec)) {
if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
rx_status->flag |= RX_FLAG_SHORTPRE;