brcm80211: fmac: move sdio used statistics to struct brcmf_sdio
[pandora-kernel.git] / drivers / net / wireless / brcm80211 / brcmfmac / dhd_sdio.c
index 84b10f1..5fb0d90 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/semaphore.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/bcma/bcma.h>
 #include <asm/unaligned.h>
 #include <defs.h>
 #include <brcmu_wifi.h>
@@ -90,7 +91,6 @@ struct rte_console {
 #include "dhd_bus.h"
 #include "dhd_proto.h"
 #include "dhd_dbg.h"
-#include <bcmchip.h>
 
 #define TXQLEN         2048    /* bulk tx queue length */
 #define TXHI           (TXQLEN - 256)  /* turn on flow control above TXHI */
@@ -309,6 +309,11 @@ struct rte_console {
 /* Flags for SDH calls */
 #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
 
+#define BRCMFMAC_FW_NAME       "brcm/brcmfmac.bin"
+#define BRCMFMAC_NV_NAME       "brcm/brcmfmac.txt"
+MODULE_FIRMWARE(BRCMFMAC_FW_NAME);
+MODULE_FIRMWARE(BRCMFMAC_NV_NAME);
+
 /*
  * Conversion of 802.1D priority to precedence level
  */
@@ -444,7 +449,7 @@ struct sdpcm_shared_le {
 
 /* misc chip info needed by some of the routines */
 /* Private data for SDIO bus interaction */
-struct brcmf_bus {
+struct brcmf_sdio {
        struct brcmf_pub *drvr;
 
        struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
@@ -541,6 +546,13 @@ struct brcmf_bus {
        uint f2rxdata;          /* Number of frame data reads */
        uint f2txdata;          /* Number of f2 frame writes */
        uint f1regdata;         /* Number of f1 register accesses */
+       uint tickcnt;           /* Number of watchdog been schedule */
+       unsigned long tx_ctlerrs;       /* Err of sending ctrl frames */
+       unsigned long tx_ctlpkts;       /* Ctrl frames sent to dongle */
+       unsigned long rx_ctlerrs;       /* Err of processing rx ctrl frames */
+       unsigned long rx_ctlpkts;       /* Ctrl frames processed from dongle */
+       unsigned long rx_readahead_cnt; /* Number of packets where header
+                                        * read-ahead was used. */
 
        u8 *ctrl_frame_buf;
        u32 ctrl_frame_len;
@@ -561,9 +573,7 @@ struct brcmf_bus {
 
        struct semaphore sdsem;
 
-       const char *fw_name;
        const struct firmware *firmware;
-       const char *nv_name;
        u32 fw_ptr;
 };
 
@@ -601,7 +611,7 @@ static void pkt_align(struct sk_buff *p, int len, int align)
 }
 
 /* To check if there's window offered */
-static bool data_ok(struct brcmf_bus *bus)
+static bool data_ok(struct brcmf_sdio *bus)
 {
        return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
               ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
@@ -612,12 +622,14 @@ static bool data_ok(struct brcmf_bus *bus)
  * adresses on the 32 bit backplane bus.
  */
 static void
-r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
+r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
 {
+       u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
        *retryvar = 0;
        do {
                *regvar = brcmf_sdcard_reg_read(bus->sdiodev,
-                               bus->ci->buscorebase + reg_offset, sizeof(u32));
+                               bus->ci->c_inf[idx].base + reg_offset,
+                               sizeof(u32));
        } while (brcmf_sdcard_regfail(bus->sdiodev) &&
                 (++(*retryvar) <= retry_limit));
        if (*retryvar) {
@@ -630,12 +642,13 @@ r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
 }
 
 static void
-w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
+w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar)
 {
+       u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
        *retryvar = 0;
        do {
                brcmf_sdcard_reg_write(bus->sdiodev,
-                                      bus->ci->buscorebase + reg_offset,
+                                      bus->ci->c_inf[idx].base + reg_offset,
                                       sizeof(u32), regval);
        } while (brcmf_sdcard_regfail(bus->sdiodev) &&
                 (++(*retryvar) <= retry_limit));
@@ -654,14 +667,14 @@ w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
 /* Packet free applicable unconditionally for sdio and sdspi.
  * Conditional if bufpool was present for gspi bus.
  */
-static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
+static void brcmf_sdbrcm_pktfree2(struct brcmf_sdio *bus, struct sk_buff *pkt)
 {
        if (bus->usebufpool)
                brcmu_pkt_buf_free_skb(pkt);
 }
 
 /* Turn backplane clock on or off */
-static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
+static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 {
        int err;
        u8 clkctl, clkreq, devctl;
@@ -683,14 +696,6 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
                        return -EBADE;
                }
 
-               if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
-                              && (bus->ci->buscorerev == 9))) {
-                       u32 dummy, retries;
-                       r_sdreg32(bus, &dummy,
-                                 offsetof(struct sdpcmd_regs, clockctlstatus),
-                                 &retries);
-               }
-
                /* Check current status */
                clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
                                               SBSDIO_FUNC1_CHIPCLKCSR, &err);
@@ -790,7 +795,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
 }
 
 /* Change idle/active SD state */
-static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
+static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -803,7 +808,7 @@ static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
 }
 
 /* Transition SD and backplane clock readiness */
-static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
+static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
 {
 #ifdef BCMDBG
        uint oldstate = bus->clkstate;
@@ -859,7 +864,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
        return 0;
 }
 
-static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
+static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep)
 {
        uint retries = 0;
 
@@ -907,13 +912,6 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
                brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
                        SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
 
-               /* Force pad isolation off if possible
-                        (in case power never toggled) */
-               if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
-                   && (bus->ci->buscorerev >= 10))
-                       brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
-                               SBSDIO_DEVICE_CTL, 0, NULL);
-
                /* Make sure the controller has the bus up */
                brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
@@ -938,13 +936,13 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
        return 0;
 }
 
-static void bus_wake(struct brcmf_bus *bus)
+static void bus_wake(struct brcmf_sdio *bus)
 {
        if (bus->sleeping)
                brcmf_sdbrcm_bussleep(bus, false);
 }
 
-static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
+static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
 {
        u32 intstatus = 0;
        u32 hmb_data;
@@ -1020,7 +1018,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
        return intstatus;
 }
 
-static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
+static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
 {
        uint retries = 0;
        u16 lastrbc;
@@ -1077,11 +1075,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
 
        /* If we can't reach the device, signal failure */
        if (err || brcmf_sdcard_regfail(bus->sdiodev))
-               bus->drvr->busstate = BRCMF_BUS_DOWN;
+               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
 }
 
 /* copy a buffer into a pkt buffer chain */
-static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_bus *bus, uint len)
+static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_sdio *bus, uint len)
 {
        uint n, ret = 0;
        struct sk_buff *p;
@@ -1103,13 +1101,35 @@ static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_bus *bus, uint len)
        return ret;
 }
 
-static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
+/* return total length of buffer chain */
+static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus)
+{
+       struct sk_buff *p;
+       uint total;
+
+       total = 0;
+       skb_queue_walk(&bus->glom, p)
+               total += p->len;
+       return total;
+}
+
+static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
+{
+       struct sk_buff *cur, *next;
+
+       skb_queue_walk_safe(&bus->glom, cur, next) {
+               skb_unlink(cur, &bus->glom);
+               brcmu_pkt_buf_free_skb(cur);
+       }
+}
+
+static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 {
        u16 dlen, totlen;
        u8 *dptr, num = 0;
 
        u16 sublen, check;
-       struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
+       struct sk_buff *pfirst, *pnext;
 
        int errcode;
        u8 chan, seq, doff, sfdoff;
@@ -1126,7 +1146,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
 
        /* If there's a descriptor, generate the packet chain */
        if (bus->glomd) {
-               pfirst = plast = pnext = NULL;
+               pfirst = pnext = NULL;
                dlen = (u16) (bus->glomd->len);
                dptr = bus->glomd->data;
                if (!dlen || (dlen & 1)) {
@@ -1187,11 +1207,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                        }
                        pfirst = pnext = NULL;
                } else {
-                       if (!skb_queue_empty(&bus->glom))
-                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
-                                       skb_unlink(pfirst, &bus->glom);
-                                       brcmu_pkt_buf_free_skb(pfirst);
-                               }
+                       brcmf_sdbrcm_free_glom(bus);
                        num = 0;
                }
 
@@ -1214,24 +1230,21 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                }
 
                pfirst = skb_peek(&bus->glom);
-               dlen = (u16) brcmu_pkttotlen(pfirst);
+               dlen = (u16) brcmf_sdbrcm_glom_len(bus);
 
                /* Do an SDIO read for the superframe.  Configurable iovar to
                 * read directly into the chained packet, or allocate a large
                 * packet and and copy into the chain.
                 */
                if (usechain) {
-                       errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
+                       errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
                                        bus->sdiodev->sbwad,
-                                       SDIO_FUNC_2,
-                                       F2SYNC, (u8 *) pfirst->data, dlen,
-                                       pfirst);
+                                       SDIO_FUNC_2, F2SYNC, &bus->glom);
                } else if (bus->dataptr) {
                        errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
                                        bus->sdiodev->sbwad,
-                                       SDIO_FUNC_2,
-                                       F2SYNC, bus->dataptr, dlen,
-                                       NULL);
+                                       SDIO_FUNC_2, F2SYNC,
+                                       bus->dataptr, dlen);
                        sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
                        if (sublen != dlen) {
                                brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
@@ -1258,10 +1271,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                bus->glomerr = 0;
                                brcmf_sdbrcm_rxfail(bus, true, false);
                                bus->rxglomfail++;
-                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
-                                       skb_unlink(pfirst, &bus->glom);
-                                       brcmu_pkt_buf_free_skb(pfirst);
-                               }
+                               brcmf_sdbrcm_free_glom(bus);
                        }
                        return 0;
                }
@@ -1334,10 +1344,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                /* Remove superframe header, remember offset */
                skb_pull(pfirst, doff);
                sfdoff = doff;
+               num = 0;
 
                /* Validate all the subframe headers */
-               for (num = 0, pnext = pfirst; pnext && !errcode;
-                    num++, pnext = pnext->next) {
+               skb_queue_walk(&bus->glom, pnext) {
+                       /* leave when invalid subframe is found */
+                       if (errcode)
+                               break;
+
                        dptr = (u8 *) (pnext->data);
                        dlen = (u16) (pnext->len);
                        sublen = get_unaligned_le16(dptr);
@@ -1370,6 +1384,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                          num, doff, sublen, SDPCM_HDRLEN);
                                errcode = -1;
                        }
+                       /* increase the subframe count */
+                       num++;
                }
 
                if (errcode) {
@@ -1383,23 +1399,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                bus->glomerr = 0;
                                brcmf_sdbrcm_rxfail(bus, true, false);
                                bus->rxglomfail++;
-                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
-                                       skb_unlink(pfirst, &bus->glom);
-                                       brcmu_pkt_buf_free_skb(pfirst);
-                               }
+                               brcmf_sdbrcm_free_glom(bus);
                        }
                        bus->nextlen = 0;
                        return 0;
                }
 
                /* Basic SD framing looks ok - process each packet (header) */
-               save_pfirst = pfirst;
-               plast = NULL;
-
-               for (num = 0; pfirst; rxseq++, pfirst = pnext) {
-                       pnext = pfirst->next;
-                       pfirst->next = NULL;
 
+               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
                        dptr = (u8 *) (pfirst->data);
                        sublen = get_unaligned_le16(dptr);
                        chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -1419,6 +1427,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                bus->rx_badseq++;
                                rxseq = seq;
                        }
+                       rxseq++;
+
 #ifdef BCMDBG
                        if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
                                printk(KERN_DEBUG "Rx Subframe Data:\n");
@@ -1431,36 +1441,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                        skb_pull(pfirst, doff);
 
                        if (pfirst->len == 0) {
+                               skb_unlink(pfirst, &bus->glom);
                                brcmu_pkt_buf_free_skb(pfirst);
-                               if (plast)
-                                       plast->next = pnext;
-                               else
-                                       save_pfirst = pnext;
-
                                continue;
-                       } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
-                                                      pfirst) != 0) {
+                       } else if (brcmf_proto_hdrpull(bus->sdiodev->dev,
+                                                      &ifidx, pfirst) != 0) {
                                brcmf_dbg(ERROR, "rx protocol error\n");
                                bus->drvr->rx_errors++;
+                               skb_unlink(pfirst, &bus->glom);
                                brcmu_pkt_buf_free_skb(pfirst);
-                               if (plast)
-                                       plast->next = pnext;
-                               else
-                                       save_pfirst = pnext;
-
                                continue;
                        }
 
-                       /* this packet will go up, link back into
-                                chain and count it */
-                       pfirst->next = pnext;
-                       plast = pfirst;
-                       num++;
-
 #ifdef BCMDBG
                        if (BRCMF_GLOM_ON()) {
                                brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
-                                         num, pfirst, pfirst->data,
+                                         bus->glom.qlen, pfirst, pfirst->data,
                                          pfirst->len, pfirst->next,
                                          pfirst->prev);
                                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
@@ -1469,19 +1465,20 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                        }
 #endif                         /* BCMDBG */
                }
-               if (num) {
+               /* sent any remaining packets up */
+               if (bus->glom.qlen) {
                        up(&bus->sdsem);
-                       brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
+                       brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
                        down(&bus->sdsem);
                }
 
                bus->rxglomframes++;
-               bus->rxglompkts += num;
+               bus->rxglompkts += bus->glom.qlen;
        }
        return num;
 }
 
-static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition,
+static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
                                        bool *pending)
 {
        DECLARE_WAITQUEUE(wait, current);
@@ -1503,7 +1500,7 @@ static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition,
        return timeout;
 }
 
-static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus)
+static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus)
 {
        if (waitqueue_active(&bus->dcmd_resp_wait))
                wake_up_interruptible(&bus->dcmd_resp_wait);
@@ -1511,7 +1508,7 @@ static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus)
        return 0;
 }
 static void
-brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
+brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 {
        uint rdlen, pad;
 
@@ -1569,8 +1566,7 @@ brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
        sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
                                bus->sdiodev->sbwad,
                                SDIO_FUNC_2,
-                               F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen,
-                               NULL);
+                               F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
        bus->f2rxdata++;
 
        /* Control frame failures need retransmission */
@@ -1601,7 +1597,7 @@ done:
 }
 
 /* Pad read to blocksize for efficiency */
-static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen)
+static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
 {
        if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) {
                *pad = bus->blocksize - (*rdlen % bus->blocksize);
@@ -1614,7 +1610,7 @@ static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen)
 }
 
 static void
-brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen,
+brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen,
                         struct sk_buff **pkt, u8 **rxbuf)
 {
        int sdret;              /* Return code from calls */
@@ -1626,9 +1622,8 @@ brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen,
        pkt_align(*pkt, rdlen, BRCMF_SDALIGN);
        *rxbuf = (u8 *) ((*pkt)->data);
        /* Read the entire frame */
-       sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
-                                     SDIO_FUNC_2, F2SYNC,
-                                     *rxbuf, rdlen, *pkt);
+       sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+                                     SDIO_FUNC_2, F2SYNC, *pkt);
        bus->f2rxdata++;
 
        if (sdret < 0) {
@@ -1647,7 +1642,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen,
 
 /* Checks the header */
 static int
-brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf,
+brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf,
                  u8 rxseq, u16 nextlen, u16 *len)
 {
        u16 check;
@@ -1703,7 +1698,7 @@ fail:
 
 /* Return true if there may be more frames to read */
 static uint
-brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
+brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
 {
        u16 len, check; /* Extracted hardware header fields */
        u8 chan, seq, doff;     /* Extracted software header fields */
@@ -1726,7 +1721,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
        *finished = false;
 
        for (rxseq = bus->rx_seq, rxleft = maxframes;
-            !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
+            !bus->rxskip && rxleft &&
+            bus->drvr->bus_if->state != BRCMF_BUS_DOWN;
             rxseq++, rxleft--) {
 
                /* Handle glomming separately */
@@ -1785,7 +1781,7 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
                                bus->nextlen = 0;
                        }
 
-                       bus->drvr->rx_readahead_cnt++;
+                       bus->rx_readahead_cnt++;
 
                        /* Handle Flow Control */
                        fcbits = SDPCM_FCMASK_VALUE(
@@ -1856,7 +1852,7 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
                /* Read frame header (hardware and software) */
                sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
                                              SDIO_FUNC_2, F2SYNC, bus->rxhdr,
-                                             BRCMF_FIRSTREAD, NULL);
+                                             BRCMF_FIRSTREAD);
                bus->f2rxhdrs++;
 
                if (sdret < 0) {
@@ -2005,9 +2001,8 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
                pkt_align(pkt, rdlen, BRCMF_SDALIGN);
 
                /* Read the remaining frame data */
-               sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad,
-                               SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
-                               rdlen, pkt);
+               sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+                                             SDIO_FUNC_2, F2SYNC, pkt);
                bus->f2rxdata++;
 
                if (sdret < 0) {
@@ -2065,7 +2060,8 @@ deliver:
                if (pkt->len == 0) {
                        brcmu_pkt_buf_free_skb(pkt);
                        continue;
-               } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
+               } else if (brcmf_proto_hdrpull(bus->sdiodev->dev, &ifidx,
+                          pkt) != 0) {
                        brcmf_dbg(ERROR, "rx protocol error\n");
                        brcmu_pkt_buf_free_skb(pkt);
                        bus->drvr->rx_errors++;
@@ -2074,7 +2070,7 @@ deliver:
 
                /* Unlock during rx call */
                up(&bus->sdsem);
-               brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
+               brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
                down(&bus->sdsem);
        }
        rxcount = maxframes - rxleft;
@@ -2094,16 +2090,8 @@ deliver:
        return rxcount;
 }
 
-static int
-brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
-                   u8 *buf, uint nbytes, struct sk_buff *pkt)
-{
-       return brcmf_sdcard_send_buf
-               (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt);
-}
-
 static void
-brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
+brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar)
 {
        up(&bus->sdsem);
        wait_event_interruptible_timeout(bus->ctrl_wait,
@@ -2113,7 +2101,7 @@ brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
 }
 
 static void
-brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
+brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 {
        if (waitqueue_active(&bus->ctrl_wait))
                wake_up_interruptible(&bus->ctrl_wait);
@@ -2122,7 +2110,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
 
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
-static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt,
+static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
                              uint chan, bool free_pkt)
 {
        int ret;
@@ -2211,9 +2199,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt,
        if (len & (ALIGNMENT - 1))
                        len = roundup(len, ALIGNMENT);
 
-       ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
-                                   SDIO_FUNC_2, F2SYNC, frame,
-                                   len, pkt);
+       ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+                                   SDIO_FUNC_2, F2SYNC, pkt);
        bus->f2txdata++;
 
        if (ret < 0) {
@@ -2251,7 +2238,7 @@ done:
        /* restore pkt buffer pointer before calling tx complete routine */
        skb_pull(pkt, SDPCM_HDRLEN + pad);
        up(&bus->sdsem);
-       brcmf_txcomplete(bus->drvr, pkt, ret != 0);
+       brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
        down(&bus->sdsem);
 
        if (free_pkt)
@@ -2260,7 +2247,7 @@ done:
        return ret;
 }
 
-static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
+static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 {
        struct sk_buff *pkt;
        u32 intstatus = 0;
@@ -2308,14 +2295,14 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
        }
 
        /* Deflow-control stack if needed */
-       if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
+       if (drvr->up && (drvr->bus_if->state == BRCMF_BUS_DATA) &&
            drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
-               brcmf_txflowcontrol(drvr, 0, OFF);
+               brcmf_txflowcontrol(bus->sdiodev->dev, 0, OFF);
 
        return cnt;
 }
 
-static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
+static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 {
        u32 intstatus, newstatus = 0;
        uint retries = 0;
@@ -2343,7 +2330,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
                                               SBSDIO_DEVICE_CTL, &err);
                if (err) {
                        brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
-                       bus->drvr->busstate = BRCMF_BUS_DOWN;
+                       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
                }
 #endif                         /* BCMDBG */
 
@@ -2353,7 +2340,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
                if (err) {
                        brcmf_dbg(ERROR, "error reading CSR: %d\n",
                                  err);
-                       bus->drvr->busstate = BRCMF_BUS_DOWN;
+                       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
                }
 
                brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
@@ -2366,7 +2353,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
                        if (err) {
                                brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
                                          err);
-                               bus->drvr->busstate = BRCMF_BUS_DOWN;
+                               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
                        }
                        devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
                        brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
@@ -2374,7 +2361,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
                        if (err) {
                                brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
                                          err);
-                               bus->drvr->busstate = BRCMF_BUS_DOWN;
+                               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
                        }
                        bus->clkstate = CLK_AVAIL;
                } else {
@@ -2476,9 +2463,9 @@ clkwait:
                (bus->clkstate == CLK_AVAIL)) {
                int ret, i;
 
-               ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
+               ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
                        SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
-                       (u32) bus->ctrl_frame_len, NULL);
+                       (u32) bus->ctrl_frame_len);
 
                if (ret < 0) {
                        /* On failure, abort the command and
@@ -2530,11 +2517,11 @@ clkwait:
                 else await next interrupt */
        /* On failed register access, all bets are off:
                 no resched or interrupts */
-       if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
+       if ((bus->drvr->bus_if->state == BRCMF_BUS_DOWN) ||
            brcmf_sdcard_regfail(bus->sdiodev)) {
                brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n",
                          brcmf_sdcard_regfail(bus->sdiodev));
-               bus->drvr->busstate = BRCMF_BUS_DOWN;
+               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
                bus->intstatus = 0;
        } else if (bus->clkstate == CLK_PENDING) {
                brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
@@ -2561,7 +2548,7 @@ clkwait:
 
 static int brcmf_sdbrcm_dpc_thread(void *data)
 {
-       struct brcmf_bus *bus = (struct brcmf_bus *) data;
+       struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
 
        allow_signal(SIGTERM);
        /* Run until signal received */
@@ -2571,12 +2558,12 @@ static int brcmf_sdbrcm_dpc_thread(void *data)
                if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
                        /* Call bus dpc unless it indicated down
                        (then clean stop) */
-                       if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
+                       if (bus->drvr->bus_if->state != BRCMF_BUS_DOWN) {
                                if (brcmf_sdbrcm_dpc(bus))
                                        complete(&bus->dpc_wait);
                        } else {
                                /* after stopping the bus, exit thread */
-                               brcmf_sdbrcm_bus_stop(bus);
+                               brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
                                bus->dpc_tsk = NULL;
                                break;
                        }
@@ -2586,10 +2573,13 @@ static int brcmf_sdbrcm_dpc_thread(void *data)
        return 0;
 }
 
-int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
+int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
        int ret = -EBADE;
        uint datalen, prec;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -2608,9 +2598,10 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
 
        /* Priority based enq */
        spin_lock_bh(&bus->txqlock);
-       if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
+       if (brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec) ==
+           false) {
                skb_pull(pkt, SDPCM_HDRLEN);
-               brcmf_txcomplete(bus->drvr, pkt, false);
+               brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
                brcmu_pkt_buf_free_skb(pkt);
                brcmf_dbg(ERROR, "out of bus->txq !!!\n");
                ret = -ENOSR;
@@ -2620,7 +2611,7 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
        spin_unlock_bh(&bus->txqlock);
 
        if (pktq_len(&bus->txq) >= TXHI)
-               brcmf_txflowcontrol(bus->drvr, 0, ON);
+               brcmf_txflowcontrol(bus->sdiodev->dev, 0, ON);
 
 #ifdef BCMDBG
        if (pktq_plen(&bus->txq, prec) > qcount[prec])
@@ -2637,7 +2628,7 @@ int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
 }
 
 static int
-brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
+brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
                 uint size)
 {
        int bcmerror = 0;
@@ -2698,7 +2689,7 @@ xfer_done:
 #ifdef BCMDBG
 #define CONSOLE_LINE_MAX       192
 
-static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
+static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
 {
        struct brcmf_console *c = &bus->console;
        u8 line[CONSOLE_LINE_MAX], ch;
@@ -2775,14 +2766,14 @@ break2:
 }
 #endif                         /* BCMDBG */
 
-static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len)
+static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
 {
        int i;
        int ret;
 
        bus->ctrl_frame_stat = false;
-       ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad,
-                                   SDIO_FUNC_2, F2SYNC, frame, len, NULL);
+       ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
+                                   SDIO_FUNC_2, F2SYNC, frame, len);
 
        if (ret < 0) {
                /* On failure, abort the command and terminate the frame */
@@ -2818,7 +2809,7 @@ static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len)
 }
 
 int
-brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        u8 *frame;
        u16 len;
@@ -2826,6 +2817,9 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
        uint retries = 0;
        u8 doff = 0;
        int ret = -1;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -2925,19 +2919,22 @@ brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
        up(&bus->sdsem);
 
        if (ret)
-               bus->drvr->tx_ctlerrs++;
+               bus->tx_ctlerrs++;
        else
-               bus->drvr->tx_ctlpkts++;
+               bus->tx_ctlpkts++;
 
        return ret ? -EIO : 0;
 }
 
 int
-brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
+brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        int timeleft;
        uint rxlen = 0;
        bool pending;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -2963,14 +2960,14 @@ brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
        }
 
        if (rxlen)
-               bus->drvr->rx_ctlpkts++;
+               bus->rx_ctlpkts++;
        else
-               bus->drvr->rx_ctlerrs++;
+               bus->rx_ctlerrs++;
 
        return rxlen ? (int)rxlen : -ETIMEDOUT;
 }
 
-static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
+static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len)
 {
        int bcmerror = 0;
 
@@ -3003,7 +3000,7 @@ err:
        return bcmerror;
 }
 
-static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
+static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
 {
        int bcmerror = 0;
        u32 varsize;
@@ -3090,55 +3087,11 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
        return bcmerror;
 }
 
-static void
-brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
-{
-       u32 regdata;
-
-       /*
-        * Must do the disable sequence first to work for
-        * arbitrary current core state.
-        */
-       brcmf_sdio_chip_coredisable(sdiodev, corebase);
-
-       /*
-        * Now do the initialization sequence.
-        * set reset while enabling the clock and
-        * forcing them on throughout the core
-        */
-       brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
-               ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
-               SBTML_RESET);
-       udelay(1);
-
-       regdata = brcmf_sdcard_reg_read(sdiodev,
-                                       CORE_SB(corebase, sbtmstatehigh), 4);
-       if (regdata & SBTMH_SERR)
-               brcmf_sdcard_reg_write(sdiodev,
-                                      CORE_SB(corebase, sbtmstatehigh), 4, 0);
-
-       regdata = brcmf_sdcard_reg_read(sdiodev,
-                                       CORE_SB(corebase, sbimstate), 4);
-       if (regdata & (SBIM_IBE | SBIM_TO))
-               brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
-                       regdata & ~(SBIM_IBE | SBIM_TO));
-
-       /* clear reset and allow it to propagate throughout the core */
-       brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
-               (SICF_FGC << SBTML_SICF_SHIFT) |
-               (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
-       udelay(1);
-
-       /* leave clock enabled */
-       brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
-               (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
-       udelay(1);
-}
-
-static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
+static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
 {
        uint retries;
        int bcmerror = 0;
+       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).
@@ -3146,10 +3099,9 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
        if (enter) {
                bus->alp_only = true;
 
-               brcmf_sdio_chip_coredisable(bus->sdiodev,
-                                             bus->ci->armcorebase);
+               ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
 
-               brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase);
+               ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
 
                /* Clear the top bit of memory */
                if (bus->ramsize) {
@@ -3158,8 +3110,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
                                         (u8 *)&zeros, 4);
                }
        } else {
-               if (!brcmf_sdio_chip_iscoreup(bus->sdiodev,
-                                             bus->ci->ramcorebase)) {
+               if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
                        brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n");
                        bcmerror = -EBADE;
                        goto fail;
@@ -3174,18 +3125,18 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
                w_sdreg32(bus, 0xFFFFFFFF,
                          offsetof(struct sdpcmd_regs, intstatus), &retries);
 
-               brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase);
+               ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
 
                /* Allow HT Clock now that the ARM is running. */
                bus->alp_only = false;
 
-               bus->drvr->busstate = BRCMF_BUS_LOAD;
+               bus->drvr->bus_if->state = BRCMF_BUS_LOAD;
        }
 fail:
        return bcmerror;
 }
 
-static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
 {
        if (bus->firmware->size < bus->fw_ptr + len)
                len = bus->firmware->size - bus->fw_ptr;
@@ -3195,10 +3146,7 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
        return len;
 }
 
-MODULE_FIRMWARE(BCM4329_FW_NAME);
-MODULE_FIRMWARE(BCM4329_NV_NAME);
-
-static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
+static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
 {
        int offset = 0;
        uint len;
@@ -3207,8 +3155,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
 
        brcmf_dbg(INFO, "Enter\n");
 
-       bus->fw_name = BCM4329_FW_NAME;
-       ret = request_firmware(&bus->firmware, bus->fw_name,
+       ret = request_firmware(&bus->firmware, BRCMFMAC_FW_NAME,
                               &bus->sdiodev->func[2]->dev);
        if (ret) {
                brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret);
@@ -3298,15 +3245,14 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len)
        return buf_len;
 }
 
-static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
+static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
 {
        uint len;
        char *memblock = NULL;
        char *bufp;
        int ret;
 
-       bus->nv_name = BCM4329_NV_NAME;
-       ret = request_firmware(&bus->firmware, bus->nv_name,
+       ret = request_firmware(&bus->firmware, BRCMFMAC_NV_NAME,
                               &bus->sdiodev->func[2]->dev);
        if (ret) {
                brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
@@ -3346,7 +3292,7 @@ err:
        return ret;
 }
 
-static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
+static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
 {
        int bcmerror = -1;
 
@@ -3379,7 +3325,7 @@ err:
 }
 
 static bool
-brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
+brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
 {
        bool ret;
 
@@ -3393,14 +3339,15 @@ brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
        return ret;
 }
 
-void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
+void brcmf_sdbrcm_bus_stop(struct device *dev)
 {
        u32 local_hostintmask;
        u8 saveclk;
        uint retries;
        int err;
-       struct sk_buff *cur;
-       struct sk_buff *next;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3429,7 +3376,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
        bus->hostintmask = 0;
 
        /* Change our idea of bus state */
-       bus->drvr->busstate = BRCMF_BUS_DOWN;
+       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
 
        /* Force clocks on backplane to be sure F2 interrupt propagates */
        saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
@@ -3460,11 +3407,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
        /* Clear any held glomming stuff */
        if (bus->glomd)
                brcmu_pkt_buf_free_skb(bus->glomd);
-       if (!skb_queue_empty(&bus->glom))
-               skb_queue_walk_safe(&bus->glom, cur, next) {
-                       skb_unlink(cur, &bus->glom);
-                       brcmu_pkt_buf_free_skb(cur);
-               }
+       brcmf_sdbrcm_free_glom(bus);
 
        /* Clear rx control and wake any waiters */
        bus->rxlen = 0;
@@ -3477,9 +3420,11 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
        up(&bus->sdsem);
 }
 
-int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
+int brcmf_sdbrcm_bus_init(struct device *dev)
 {
-       struct brcmf_bus *bus = drvr->bus;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
        unsigned long timeout;
        uint retries = 0;
        u8 ready, enable;
@@ -3489,7 +3434,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
        brcmf_dbg(TRACE, "Enter\n");
 
        /* try to download image and nvram to the dongle */
-       if (drvr->busstate == BRCMF_BUS_DOWN) {
+       if (bus_if->state == BRCMF_BUS_DOWN) {
                if (!(brcmf_sdbrcm_download_firmware(bus)))
                        return -1;
        }
@@ -3498,7 +3443,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
                return 0;
 
        /* Start the watchdog timer */
-       bus->drvr->tickcnt = 0;
+       bus->tickcnt = 0;
        brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
 
        down(&bus->sdsem);
@@ -3555,7 +3500,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
                                       SBSDIO_WATERMARK, 8, &err);
 
                /* Set bus state according to enable result */
-               drvr->busstate = BRCMF_BUS_DATA;
+               bus_if->state = BRCMF_BUS_DATA;
        }
 
        else {
@@ -3570,7 +3515,7 @@ int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr)
                               SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
 
        /* If we didn't come up, turn off backplane clock */
-       if (drvr->busstate != BRCMF_BUS_DATA)
+       if (bus_if->state != BRCMF_BUS_DATA)
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 
 exit:
@@ -3581,7 +3526,7 @@ exit:
 
 void brcmf_sdbrcm_isr(void *arg)
 {
-       struct brcmf_bus *bus = (struct brcmf_bus *) arg;
+       struct brcmf_sdio *bus = (struct brcmf_sdio *) arg;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3590,7 +3535,7 @@ void brcmf_sdbrcm_isr(void *arg)
                return;
        }
 
-       if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
+       if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN) {
                brcmf_dbg(ERROR, "bus is down. we have nothing to do\n");
                return;
        }
@@ -3613,14 +3558,14 @@ void brcmf_sdbrcm_isr(void *arg)
                complete(&bus->dpc_wait);
 }
 
-static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
+static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
 {
-       struct brcmf_bus *bus;
+#ifdef BCMDBG
+       struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
+#endif /* BCMDBG */
 
        brcmf_dbg(TIMER, "Enter\n");
 
-       bus = drvr->bus;
-
        /* Ignore the timer if simulating bus down */
        if (bus->sleeping)
                return false;
@@ -3664,7 +3609,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
        }
 #ifdef BCMDBG
        /* Poll for console output periodically */
-       if (drvr->busstate == BRCMF_BUS_DATA && bus->console_interval != 0) {
+       if (bus_if->state == BRCMF_BUS_DATA &&
+           bus->console_interval != 0) {
                bus->console.count += BRCMF_WD_POLL_MS;
                if (bus->console.count >= bus->console_interval) {
                        bus->console.count -= bus->console_interval;
@@ -3699,10 +3645,12 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
 {
        if (chipid == BCM4329_CHIP_ID)
                return true;
+       if (chipid == BCM4330_CHIP_ID)
+               return true;
        return false;
 }
 
-static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
+static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3714,7 +3662,7 @@ static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
        bus->databuf = NULL;
 }
 
-static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus)
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3749,127 +3697,14 @@ fail:
        return false;
 }
 
-/* SDIO Pad drive strength to select value mappings */
-struct sdiod_drive_str {
-       u8 strength;    /* Pad Drive Strength in mA */
-       u8 sel;         /* Chip-specific select value */
-};
-
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
-       {
-       4, 0x2}, {
-       2, 0x3}, {
-       1, 0x0}, {
-       0, 0x0}
-       };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
-       {
-       12, 0x7}, {
-       10, 0x6}, {
-       8, 0x5}, {
-       6, 0x4}, {
-       4, 0x2}, {
-       2, 0x1}, {
-       0, 0x0}
-       };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
-static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
-       {
-       32, 0x7}, {
-       26, 0x6}, {
-       22, 0x5}, {
-       16, 0x4}, {
-       12, 0x3}, {
-       8, 0x2}, {
-       4, 0x1}, {
-       0, 0x0}
-       };
-
-#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
-
-static char *brcmf_chipname(uint chipid, char *buf, uint len)
-{
-       const char *fmt;
-
-       fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
-       snprintf(buf, len, fmt, chipid);
-       return buf;
-}
-
-static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
-                                                  u32 drivestrength) {
-       struct sdiod_drive_str *str_tab = NULL;
-       u32 str_mask = 0;
-       u32 str_shift = 0;
-       char chn[8];
-
-       if (!(bus->ci->cccaps & CC_CAP_PMU))
-               return;
-
-       switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
-               str_mask = 0x30000000;
-               str_shift = 28;
-               break;
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
-               str_mask = 0x00003800;
-               str_shift = 11;
-               break;
-       case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
-               str_mask = 0x00003800;
-               str_shift = 11;
-               break;
-       default:
-               brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
-                         brcmf_chipname(bus->ci->chip, chn, 8),
-                         bus->ci->chiprev, bus->ci->pmurev);
-               break;
-       }
-
-       if (str_tab != NULL) {
-               u32 drivestrength_sel = 0;
-               u32 cc_data_temp;
-               int i;
-
-               for (i = 0; str_tab[i].strength != 0; i++) {
-                       if (drivestrength >= str_tab[i].strength) {
-                               drivestrength_sel = str_tab[i].sel;
-                               break;
-                       }
-               }
-
-               brcmf_sdcard_reg_write(bus->sdiodev,
-                       CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
-                       4, 1);
-               cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev,
-                       CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
-               cc_data_temp &= ~str_mask;
-               drivestrength_sel <<= str_shift;
-               cc_data_temp |= drivestrength_sel;
-               brcmf_sdcard_reg_write(bus->sdiodev,
-                       CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
-                       4, cc_data_temp);
-
-               brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
-                         drivestrength, cc_data_temp);
-       }
-}
-
 static bool
-brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
+brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
 {
        u8 clkctl = 0;
        int err = 0;
        int reg_addr;
        u32 reg_val;
+       u8 idx;
 
        bus->alp_only = true;
 
@@ -3912,7 +3747,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
                goto fail;
        }
 
-       brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH);
+       brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
+                                         SDIO_DRIVE_STRENGTH);
 
        /* Get info on the SOCRAM cores... */
        bus->ramsize = bus->ci->ramsize;
@@ -3922,7 +3758,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
        }
 
        /* Set core control so an SDIO reset does a backplane reset */
-       reg_addr = bus->ci->buscorebase +
+       idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+       reg_addr = bus->ci->c_inf[idx].base +
                   offsetof(struct sdpcmd_regs, corecontrol);
        reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32));
        brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32),
@@ -3946,7 +3783,7 @@ fail:
        return false;
 }
 
-static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus)
+static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3954,7 +3791,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus)
        brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
                               SDIO_FUNC_ENABLE_1, NULL);
 
-       bus->drvr->busstate = BRCMF_BUS_DOWN;
+       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
        bus->sleeping = false;
        bus->rxflow = false;
 
@@ -3981,7 +3818,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus)
 static int
 brcmf_sdbrcm_watchdog_thread(void *data)
 {
-       struct brcmf_bus *bus = (struct brcmf_bus *)data;
+       struct brcmf_sdio *bus = (struct brcmf_sdio *)data;
 
        allow_signal(SIGTERM);
        /* Run until signal received */
@@ -3989,9 +3826,9 @@ brcmf_sdbrcm_watchdog_thread(void *data)
                if (kthread_should_stop())
                        break;
                if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
-                       brcmf_sdbrcm_bus_watchdog(bus->drvr);
+                       brcmf_sdbrcm_bus_watchdog(bus);
                        /* Count the tick for reference */
-                       bus->drvr->tickcnt++;
+                       bus->tickcnt++;
                } else
                        break;
        }
@@ -4001,7 +3838,7 @@ brcmf_sdbrcm_watchdog_thread(void *data)
 static void
 brcmf_sdbrcm_watchdog(unsigned long data)
 {
-       struct brcmf_bus *bus = (struct brcmf_bus *)data;
+       struct brcmf_sdio *bus = (struct brcmf_sdio *)data;
 
        if (bus->watchdog_tsk) {
                complete(&bus->watchdog_wait);
@@ -4012,23 +3849,14 @@ brcmf_sdbrcm_watchdog(unsigned long data)
        }
 }
 
-static void
-brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       kfree(bus->ci);
-       bus->ci = NULL;
-}
-
-static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
+static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
        if (bus->ci) {
                brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
-               brcmf_sdbrcm_chip_detach(bus);
+               brcmf_sdio_chip_detach(&bus->ci);
                if (bus->vars && bus->varsz)
                        kfree(bus->vars);
                bus->vars = NULL;
@@ -4038,7 +3866,7 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
 }
 
 /* Detach and free everything */
-static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
+static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -4046,8 +3874,8 @@ static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
                /* De-register interrupt handler */
                brcmf_sdcard_intr_dereg(bus->sdiodev);
 
-               if (bus->drvr) {
-                       brcmf_detach(bus->drvr);
+               if (bus->sdiodev->bus_if->drvr) {
+                       brcmf_detach(bus->sdiodev->dev);
                        brcmf_sdbrcm_release_dongle(bus);
                        bus->drvr = NULL;
                }
@@ -4060,21 +3888,10 @@ static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
        brcmf_dbg(TRACE, "Disconnected\n");
 }
 
-void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
-                        u32 regsva, struct brcmf_sdio_dev *sdiodev)
+void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
 {
        int ret;
-       struct brcmf_bus *bus;
-
-       /* Init global variables at run-time, not as part of the declaration.
-        * This is required to support init/de-init of the driver.
-        * Initialization
-        * of globals as part of the declaration results in non-deterministic
-        * behavior since the value of the globals may be different on the
-        * first time that the driver is initialized vs subsequent
-        * initializations.
-        */
-       brcmf_c_init();
+       struct brcmf_sdio *bus;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -4082,7 +3899,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
         * regsva == SI_ENUM_BASE*/
 
        /* Allocate private bus interface state */
-       bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
+       bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC);
        if (!bus)
                goto fail;
 
@@ -4134,7 +3951,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
        }
 
        /* Attach to the brcmf/OS/network interface */
-       bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
+       bus->drvr = brcmf_attach(bus, SDPCM_RESERVE, bus->sdiodev->dev);
        if (!bus->drvr) {
                brcmf_dbg(ERROR, "brcmf_attach failed\n");
                goto fail;
@@ -4163,7 +3980,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
        brcmf_dbg(INFO, "completed!!\n");
 
        /* if firmware path present try to download and bring up bus */
-       ret = brcmf_bus_start(bus->drvr);
+       ret = brcmf_bus_start(bus->sdiodev->dev);
        if (ret != 0) {
                if (ret == -ENOLINK) {
                        brcmf_dbg(ERROR, "dongle is not responding\n");
@@ -4172,7 +3989,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
        }
 
        /* add interface and open for business */
-       if (brcmf_add_if((struct brcmf_info *)bus->drvr, 0, "wlan%d", NULL)) {
+       if (brcmf_add_if(bus->sdiodev->dev, 0, "wlan%d", NULL)) {
                brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
                goto fail;
        }
@@ -4186,7 +4003,7 @@ fail:
 
 void brcmf_sdbrcm_disconnect(void *ptr)
 {
-       struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
+       struct brcmf_sdio *bus = (struct brcmf_sdio *)ptr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -4196,13 +4013,8 @@ void brcmf_sdbrcm_disconnect(void *ptr)
        brcmf_dbg(TRACE, "Disconnected\n");
 }
 
-struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
-{
-       return &bus->sdiodev->func[2]->dev;
-}
-
 void
-brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
+brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick)
 {
        /* Totally stop the timer */
        if (!wdtick && bus->wd_timer_valid == true) {
@@ -4213,7 +4025,7 @@ brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
        }
 
        /* don't start the wd until fw is loaded */
-       if (bus->drvr->busstate == BRCMF_BUS_DOWN)
+       if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN)
                return;
 
        if (wdtick) {