aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c97
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c105
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c127
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c45
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h22
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c8
9 files changed, 305 insertions, 105 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index e925290..4add7da 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -39,37 +39,113 @@
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-static void brcmf_sdioh_irqhandler(struct sdio_func *func)
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
{
- struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
- brcmf_dbg(TRACE, "***IRQHandler\n");
+ brcmf_dbg(INTR, "oob intr triggered\n");
- sdio_release_host(func);
+ /*
+ * out-of-band interrupt is level-triggered which won't
+ * be cleared until dpc
+ */
+ if (sdiodev->irq_en) {
+ disable_irq_nosync(irq);
+ sdiodev->irq_en = false;
+ }
brcmf_sdbrcm_isr(sdiodev->bus);
- sdio_claim_host(func);
+ return IRQ_HANDLED;
+}
+
+int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
+{
+ int ret = 0;
+ u8 data;
+ unsigned long flags;
+
+ brcmf_dbg(TRACE, "Entering\n");
+
+ brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
+ ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
+ sdiodev->irq_flags, "brcmf_oob_intr",
+ &sdiodev->func[1]->card->dev);
+ if (ret != 0)
+ return ret;
+ spin_lock_init(&sdiodev->irq_en_lock);
+ spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
+ sdiodev->irq_en = true;
+ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+
+ ret = enable_irq_wake(sdiodev->irq);
+ if (ret != 0)
+ return ret;
+ sdiodev->irq_wake = true;
+
+ /* must configure SDIO_CCCR_IENx to enable irq */
+ data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0,
+ SDIO_CCCR_IENx, &ret);
+ data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx,
+ data, &ret);
+
+ /* redirect, configure ane enable io for interrupt signal */
+ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
+ if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH)
+ data |= SDIO_SEPINT_ACT_HI;
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
+ data, &ret);
+
+ return 0;
+}
+
+int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+{
+ brcmf_dbg(TRACE, "Entering\n");
+
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
+ 0, NULL);
+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL);
+
+ if (sdiodev->irq_wake) {
+ disable_irq_wake(sdiodev->irq);
+ sdiodev->irq_wake = false;
+ }
+ free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
+ sdiodev->irq_en = false;
+
+ return 0;
+}
+#else /* CONFIG_BRCMFMAC_SDIO_OOB */
+static void brcmf_sdio_irqhandler(struct sdio_func *func)
+{
+ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+
+ brcmf_dbg(INTR, "ib intr triggered\n");
+
+ brcmf_sdbrcm_isr(sdiodev->bus);
}
/* dummy handler for SDIO function 2 interrupt */
-static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func)
+static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
{
}
-int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
sdio_claim_host(sdiodev->func[1]);
- sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
- sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler);
+ sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
+ sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
sdio_release_host(sdiodev->func[1]);
return 0;
}
-int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(TRACE, "Entering\n");
@@ -80,6 +156,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
return 0;
}
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
int *err)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 758c115..dd07d33 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -27,6 +27,7 @@
#include <linux/errno.h>
#include <linux/sched.h> /* request_irq() */
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <net/cfg80211.h>
#include <defs.h>
@@ -55,6 +56,15 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+static struct list_head oobirq_lh;
+struct brcmf_sdio_oobirq {
+ unsigned int irq;
+ unsigned long flags;
+ struct list_head list;
+};
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
+
static bool
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
{
@@ -107,7 +117,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
}
sdio_release_host(sdfunc);
}
- } else if (regaddr == SDIO_CCCR_ABORT) {
+ } else if ((regaddr == SDIO_CCCR_ABORT) ||
+ (regaddr == SDIO_CCCR_IENx)) {
sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
GFP_KERNEL);
if (!sdfunc)
@@ -467,12 +478,40 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
}
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
+{
+ struct brcmf_sdio_oobirq *oobirq_entry;
+
+ if (list_empty(&oobirq_lh)) {
+ brcmf_dbg(ERROR, "no valid oob irq resource\n");
+ return -ENXIO;
+ }
+
+ oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
+ list);
+
+ sdiodev->irq = oobirq_entry->irq;
+ sdiodev->irq_flags = oobirq_entry->flags;
+ list_del(&oobirq_entry->list);
+ kfree(oobirq_entry);
+
+ return 0;
+}
+#else
+static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
+{
+ return 0;
+}
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
+
static int brcmf_ops_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret = 0;
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
+
brcmf_dbg(TRACE, "Enter\n");
brcmf_dbg(TRACE, "func->class=%x\n", func->class);
brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
@@ -511,6 +550,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
sdiodev = dev_get_drvdata(&func->card->dev);
if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
return -ENODEV;
+
+ ret = brcmf_sdio_getintrcfg(sdiodev);
+ if (ret)
+ return ret;
sdiodev->func[2] = func;
bus_if = sdiodev->bus_if;
@@ -603,6 +646,65 @@ static struct sdio_driver brcmf_sdmmc_driver = {
#endif /* CONFIG_PM_SLEEP */
};
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+static int brcmf_sdio_pd_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct brcmf_sdio_oobirq *oobirq_entry;
+ int i, ret;
+
+ INIT_LIST_HEAD(&oobirq_lh);
+
+ for (i = 0; ; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res)
+ break;
+
+ oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
+ GFP_KERNEL);
+ oobirq_entry->irq = res->start;
+ oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
+ list_add_tail(&oobirq_entry->list, &oobirq_lh);
+ }
+ if (i == 0)
+ return -ENXIO;
+
+ ret = sdio_register_driver(&brcmf_sdmmc_driver);
+
+ if (ret)
+ brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
+
+ return ret;
+}
+
+static struct platform_driver brcmf_sdio_pd = {
+ .probe = brcmf_sdio_pd_probe,
+ .driver = {
+ .name = "brcmf_sdio_pd"
+ }
+};
+
+void brcmf_sdio_exit(void)
+{
+ brcmf_dbg(TRACE, "Enter\n");
+
+ sdio_unregister_driver(&brcmf_sdmmc_driver);
+
+ platform_driver_unregister(&brcmf_sdio_pd);
+}
+
+void brcmf_sdio_init(void)
+{
+ int ret;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ ret = platform_driver_register(&brcmf_sdio_pd);
+
+ if (ret)
+ brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret);
+}
+#else
void brcmf_sdio_exit(void)
{
brcmf_dbg(TRACE, "Enter\n");
@@ -621,3 +723,4 @@ void brcmf_sdio_init(void)
if (ret)
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
}
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 07686a7..9f63701 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -632,7 +632,6 @@ extern const struct bcmevent_name bcmevent_names[];
extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
char *buf, uint len);
-extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index b3e3b7f..a5c15ca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -421,6 +421,7 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
skb_pull(pktbuf, BDC_HEADER_LEN);
+ skb_pull(pktbuf, h->data_offset << 2);
return 0;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 4187435..236cb9f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -799,7 +799,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
{
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
"event_msgs" + '\0' + bitvec */
- uint up = 0;
char buf[128], *ptr;
u32 dongle_align = drvr->bus_if->align;
u32 glom = 0;
@@ -853,9 +852,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
- /* Force STA UP */
- brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
-
/* Setup event_msgs */
brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
iovbuf, sizeof(iovbuf));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 2a1e5ae..8933f9b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -799,6 +799,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
struct brcmf_bus *bus_if = drvr->bus_if;
u32 toe_ol;
s32 ret = 0;
+ uint up = 0;
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
@@ -822,6 +823,10 @@ static int brcmf_netdev_open(struct net_device *ndev)
drvr->iflist[ifp->idx]->ndev->features &=
~NETIF_F_IP_CSUM;
}
+
+ /* make sure RF is ready for work */
+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
+
/* Allow transmit calls */
netif_start_queue(ndev);
drvr->bus_if->drvr_up = true;
@@ -843,6 +848,63 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};
+static int brcmf_net_attach(struct brcmf_if *ifp)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct net_device *ndev;
+ u8 temp_addr[ETH_ALEN];
+
+ brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
+
+ ndev = drvr->iflist[ifp->idx]->ndev;
+ ndev->netdev_ops = &brcmf_netdev_ops_pri;
+
+ /*
+ * determine mac address to use
+ */
+ if (is_valid_ether_addr(ifp->mac_addr))
+ memcpy(temp_addr, ifp->mac_addr, ETH_ALEN);
+ else
+ memcpy(temp_addr, drvr->mac, ETH_ALEN);
+
+ if (ifp->idx == 1) {
+ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
+ /* ACCESSPOINT INTERFACE CASE */
+ temp_addr[0] |= 0X02; /* set bit 2 ,
+ - Locally Administered address */
+
+ }
+ ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
+ ndev->ethtool_ops = &brcmf_ethtool_ops;
+
+ drvr->rxsz = ndev->mtu + ndev->hard_header_len +
+ drvr->hdrlen;
+
+ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
+
+ /* attach to cfg80211 for primary interface */
+ if (!ifp->idx) {
+ drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr);
+ if (drvr->config == NULL) {
+ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
+ goto fail;
+ }
+ }
+
+ if (register_netdev(ndev) != 0) {
+ brcmf_dbg(ERROR, "couldn't register the net device\n");
+ goto fail;
+ }
+
+ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
+
+ return 0;
+
+fail:
+ ndev->netdev_ops = NULL;
+ return -EBADE;
+}
+
int
brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
{
@@ -882,7 +944,7 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
if (mac_addr != NULL)
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
- if (brcmf_net_attach(drvr, ifp->idx)) {
+ if (brcmf_net_attach(ifp)) {
brcmf_dbg(ERROR, "brcmf_net_attach failed");
free_netdev(ifp->ndev);
drvr->iflist[ifidx] = NULL;
@@ -1016,69 +1078,16 @@ int brcmf_bus_start(struct device *dev)
if (ret < 0)
return ret;
+ /* add primary networking interface */
+ ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac);
+ if (ret < 0)
+ return ret;
+
/* signal bus ready */
bus_if->state = BRCMF_BUS_DATA;
return 0;
}
-int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
-{
- struct net_device *ndev;
- u8 temp_addr[ETH_ALEN] = {
- 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
-
- brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
-
- ndev = drvr->iflist[ifidx]->ndev;
- ndev->netdev_ops = &brcmf_netdev_ops_pri;
-
- /*
- * We have to use the primary MAC for virtual interfaces
- */
- if (ifidx != 0) {
- /* for virtual interfaces use the primary MAC */
- memcpy(temp_addr, drvr->mac, ETH_ALEN);
-
- }
-
- if (ifidx == 1) {
- brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
- /* ACCESSPOINT INTERFACE CASE */
- temp_addr[0] |= 0X02; /* set bit 2 ,
- - Locally Administered address */
-
- }
- ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
- ndev->ethtool_ops = &brcmf_ethtool_ops;
-
- drvr->rxsz = ndev->mtu + ndev->hard_header_len +
- drvr->hdrlen;
-
- memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
-
- /* attach to cfg80211 for primary interface */
- if (!ifidx) {
- drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr);
- if (drvr->config == NULL) {
- brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
- goto fail;
- }
- }
-
- if (register_netdev(ndev) != 0) {
- brcmf_dbg(ERROR, "couldn't register the net device\n");
- goto fail;
- }
-
- brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
-
- return 0;
-
-fail:
- ndev->netdev_ops = NULL;
- return -EBADE;
-}
-
static void brcmf_bus_detach(struct brcmf_pub *drvr)
{
brcmf_dbg(TRACE, "Enter\n");
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index e2b34e1..149ee67 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2352,6 +2352,24 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
up(&bus->sdsem);
}
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
+ if (!bus->sdiodev->irq_en && !bus->ipend) {
+ enable_irq(bus->sdiodev->irq);
+ bus->sdiodev->irq_en = true;
+ }
+ spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
+}
+#else
+static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
+{
+}
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
+
static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
{
u32 intstatus, newstatus = 0;
@@ -2509,6 +2527,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
bus->intstatus = intstatus;
clkwait:
+ brcmf_sdbrcm_clrintr(bus);
+
if (data_ok(bus) && bus->ctrl_frame_stat &&
(bus->clkstate == CLK_AVAIL)) {
int ret, i;
@@ -3508,8 +3528,14 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+ if (ret == 0) {
+ ret = brcmf_sdio_intr_register(bus->sdiodev);
+ if (ret != 0)
+ brcmf_dbg(ERROR, "intr register failed:%d\n", ret);
+ }
+
/* If we didn't come up, turn off backplane clock */
- if (!ret)
+ if (bus_if->state != BRCMF_BUS_DATA)
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
exit:
@@ -3867,7 +3893,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
if (bus) {
/* De-register interrupt handler */
- brcmf_sdcard_intr_dereg(bus->sdiodev);
+ brcmf_sdio_intr_unregister(bus->sdiodev);
if (bus->sdiodev->bus_if->drvr) {
brcmf_detach(bus->sdiodev->dev);
@@ -3968,15 +3994,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
goto fail;
}
- /* Register interrupt callback, but mask it (not operational yet). */
- brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n");
- ret = brcmf_sdcard_intr_reg(bus->sdiodev);
- if (ret != 0) {
- brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret);
- goto fail;
- }
- brcmf_dbg(INTR, "registered SDIO interrupt function ok\n");
-
brcmf_dbg(INFO, "completed!!\n");
/* if firmware path present try to download and bring up bus */
@@ -3988,12 +4005,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
}
}
- /* add interface and open for business */
- if (brcmf_add_if(bus->sdiodev->dev, 0, "wlan%d", NULL)) {
- brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
- goto fail;
- }
-
return bus;
fail:
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 0281d20..7010eaf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -43,6 +43,13 @@
/* as of sdiod rev 0, supports 3 functions */
#define SBSDIO_NUM_FUNCTION 3
+/* function 0 vendor specific CCCR registers */
+#define SDIO_CCCR_BRCM_SEPINT 0xf2
+
+#define SDIO_SEPINT_MASK 0x01
+#define SDIO_SEPINT_OE 0x02
+#define SDIO_SEPINT_ACT_HI 0x04
+
/* function 1 miscellaneous registers */
/* sprom command and status */
@@ -144,13 +151,18 @@ struct brcmf_sdio_dev {
wait_queue_head_t request_buffer_wait;
struct device *dev;
struct brcmf_bus *bus_if;
+#ifdef CONFIG_BRCMFMAC_SDIO_OOB
+ unsigned int irq; /* oob interrupt number */
+ unsigned long irq_flags; /* board specific oob flags */
+ bool irq_en; /* irq enable flags */
+ spinlock_t irq_en_lock;
+ bool irq_wake; /* irq wake enable flags */
+#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
};
-/* Register/deregister device interrupt handler. */
-extern int
-brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev);
-
-extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev);
+/* Register/deregister interrupt handler. */
+extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
+extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
* fn: function number
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 8236422..1d67ecf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -1383,14 +1383,6 @@ static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
goto fail;
}
- /* add interface and open for business */
- ret = brcmf_add_if(dev, 0, "wlan%d", NULL);
- if (ret) {
- brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
- brcmf_detach(dev);
- goto fail;
- }
-
return 0;
fail:
/* Release resources in reverse order */