aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2013-04-12 04:55:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-12 14:27:55 -0400
commit668761ac01d6f5a36b8e5a24d4e154550e2c4c3b (patch)
treeaaf5ab3af476a7b293b0b8d9e78aef42ea77c2d6 /drivers/net/wireless
parent979c29205ffa607c59ba2c9f9c083b967d356c97 (diff)
brcmfmac: define and use platform specific data for SDIO.
This patch adds support for platform specific data for SDIO fullmac devices. Currently OOB interrupts are configured by Kconfig BRCMFMAC_SDIO_OOB but that is now determined dynamically by checking availibility of platform data. Cc: Hauke Mehrtens <hauke@hauke-m.de> Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Piotr Haber <phaber@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c155
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c114
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h6
5 files changed, 126 insertions, 187 deletions
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 747e9317dabd..fc8a0fa6d3b2 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -37,15 +37,6 @@ config BRCMFMAC_SDIO
37 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to 37 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
38 use the driver for a SDIO wireless card. 38 use the driver for a SDIO wireless card.
39 39
40config BRCMFMAC_SDIO_OOB
41 bool "Out of band interrupt support for SDIO interface chipset"
42 depends on BRCMFMAC_SDIO
43 ---help---
44 This option enables out-of-band interrupt support for Broadcom
45 SDIO Wifi chipset using fullmac in order to gain better
46 performance and deep sleep wake up capability on certain
47 platforms. Say N if you are unsure.
48
49config BRCMFMAC_USB 40config BRCMFMAC_USB
50 bool "USB bus interface support for FullMAC driver" 41 bool "USB bus interface support for FullMAC driver"
51 depends on USB 42 depends on USB
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index aa51f370be49..4891e3df2058 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -25,6 +25,7 @@
25#include <linux/mmc/sdio.h> 25#include <linux/mmc/sdio.h>
26#include <linux/mmc/sdio_func.h> 26#include <linux/mmc/sdio_func.h>
27#include <linux/mmc/card.h> 27#include <linux/mmc/card.h>
28#include <linux/platform_data/brcmfmac-sdio.h>
28 29
29#include <defs.h> 30#include <defs.h>
30#include <brcm_hw_ids.h> 31#include <brcm_hw_ids.h>
@@ -37,16 +38,15 @@
37 38
38#define SDIOH_API_ACCESS_RETRY_LIMIT 2 39#define SDIOH_API_ACCESS_RETRY_LIMIT 2
39 40
40#ifdef CONFIG_BRCMFMAC_SDIO_OOB 41
41static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id) 42static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
42{ 43{
43 struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); 44 struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
44 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; 45 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
45 46
46 brcmf_dbg(INTR, "oob intr triggered\n"); 47 brcmf_dbg(INTR, "OOB intr triggered\n");
47 48
48 /* 49 /* out-of-band interrupt is level-triggered which won't
49 * out-of-band interrupt is level-triggered which won't
50 * be cleared until dpc 50 * be cleared until dpc
51 */ 51 */
52 if (sdiodev->irq_en) { 52 if (sdiodev->irq_en) {
@@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
59 return IRQ_HANDLED; 59 return IRQ_HANDLED;
60} 60}
61 61
62int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) 62static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
63{
64 int ret = 0;
65 u8 data;
66 unsigned long flags;
67
68 brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
69
70 ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
71 sdiodev->irq_flags, "brcmf_oob_intr",
72 &sdiodev->func[1]->dev);
73 if (ret != 0)
74 return ret;
75 spin_lock_init(&sdiodev->irq_en_lock);
76 spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
77 sdiodev->irq_en = true;
78 spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
79
80 ret = enable_irq_wake(sdiodev->irq);
81 if (ret != 0)
82 return ret;
83 sdiodev->irq_wake = true;
84
85 sdio_claim_host(sdiodev->func[1]);
86
87 /* must configure SDIO_CCCR_IENx to enable irq */
88 data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
89 data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
90 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
91
92 /* redirect, configure and enable io for interrupt signal */
93 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
94 if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
95 data |= SDIO_SEPINT_ACT_HI;
96 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
97
98 sdio_release_host(sdiodev->func[1]);
99
100 return 0;
101}
102
103int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
104{
105 brcmf_dbg(SDIO, "Entering\n");
106
107 sdio_claim_host(sdiodev->func[1]);
108 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
109 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
110 sdio_release_host(sdiodev->func[1]);
111
112 if (sdiodev->irq_wake) {
113 disable_irq_wake(sdiodev->irq);
114 sdiodev->irq_wake = false;
115 }
116 free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
117 sdiodev->irq_en = false;
118
119 return 0;
120}
121#else /* CONFIG_BRCMFMAC_SDIO_OOB */
122static void brcmf_sdio_irqhandler(struct sdio_func *func)
123{ 63{
124 struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); 64 struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
125 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; 65 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
126 66
127 brcmf_dbg(INTR, "ib intr triggered\n"); 67 brcmf_dbg(INTR, "IB intr triggered\n");
128 68
129 brcmf_sdbrcm_isr(sdiodev->bus); 69 brcmf_sdbrcm_isr(sdiodev->bus);
130} 70}
@@ -136,12 +76,56 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
136 76
137int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) 77int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
138{ 78{
139 brcmf_dbg(SDIO, "Entering\n"); 79 int ret = 0;
80 u8 data;
81 unsigned long flags;
140 82
141 sdio_claim_host(sdiodev->func[1]); 83 if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
142 sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); 84 brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
143 sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); 85 sdiodev->pdata->oob_irq_nr);
144 sdio_release_host(sdiodev->func[1]); 86 ret = request_irq(sdiodev->pdata->oob_irq_nr,
87 brcmf_sdio_oob_irqhandler,
88 sdiodev->pdata->oob_irq_flags,
89 "brcmf_oob_intr",
90 &sdiodev->func[1]->dev);
91 if (ret != 0) {
92 brcmf_err("request_irq failed %d\n", ret);
93 return ret;
94 }
95 sdiodev->oob_irq_requested = true;
96 spin_lock_init(&sdiodev->irq_en_lock);
97 spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
98 sdiodev->irq_en = true;
99 spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
100
101 ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
102 if (ret != 0) {
103 brcmf_err("enable_irq_wake failed %d\n", ret);
104 return ret;
105 }
106 sdiodev->irq_wake = true;
107
108 sdio_claim_host(sdiodev->func[1]);
109
110 /* must configure SDIO_CCCR_IENx to enable irq */
111 data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
112 data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
113 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
114
115 /* redirect, configure and enable io for interrupt signal */
116 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
117 if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
118 data |= SDIO_SEPINT_ACT_HI;
119 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
120
121 sdio_release_host(sdiodev->func[1]);
122 } else {
123 brcmf_dbg(SDIO, "Entering\n");
124 sdio_claim_host(sdiodev->func[1]);
125 sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
126 sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
127 sdio_release_host(sdiodev->func[1]);
128 }
145 129
146 return 0; 130 return 0;
147} 131}
@@ -150,14 +134,31 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
150{ 134{
151 brcmf_dbg(SDIO, "Entering\n"); 135 brcmf_dbg(SDIO, "Entering\n");
152 136
153 sdio_claim_host(sdiodev->func[1]); 137 if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
154 sdio_release_irq(sdiodev->func[2]); 138 sdio_claim_host(sdiodev->func[1]);
155 sdio_release_irq(sdiodev->func[1]); 139 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
156 sdio_release_host(sdiodev->func[1]); 140 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
141 sdio_release_host(sdiodev->func[1]);
142
143 if (sdiodev->oob_irq_requested) {
144 sdiodev->oob_irq_requested = false;
145 if (sdiodev->irq_wake) {
146 disable_irq_wake(sdiodev->pdata->oob_irq_nr);
147 sdiodev->irq_wake = false;
148 }
149 free_irq(sdiodev->pdata->oob_irq_nr,
150 &sdiodev->func[1]->dev);
151 sdiodev->irq_en = false;
152 }
153 } else {
154 sdio_claim_host(sdiodev->func[1]);
155 sdio_release_irq(sdiodev->func[2]);
156 sdio_release_irq(sdiodev->func[1]);
157 sdio_release_host(sdiodev->func[1]);
158 }
157 159
158 return 0; 160 return 0;
159} 161}
160#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
161 162
162int 163int
163brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) 164brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index b1ea1036e825..44fa0cdbf97b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -26,6 +26,7 @@
26#include <linux/sched.h> /* request_irq() */ 26#include <linux/sched.h> /* request_irq() */
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/platform_data/brcmfmac-sdio.h>
29#include <net/cfg80211.h> 30#include <net/cfg80211.h>
30 31
31#include <defs.h> 32#include <defs.h>
@@ -62,14 +63,8 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
62}; 63};
63MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); 64MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
64 65
65#ifdef CONFIG_BRCMFMAC_SDIO_OOB 66static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
66static struct list_head oobirq_lh; 67
67struct brcmf_sdio_oobirq {
68 unsigned int irq;
69 unsigned long flags;
70 struct list_head list;
71};
72#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
73 68
74static bool 69static bool
75brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) 70brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
@@ -428,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
428 423
429} 424}
430 425
431#ifdef CONFIG_BRCMFMAC_SDIO_OOB
432static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
433{
434 struct brcmf_sdio_oobirq *oobirq_entry;
435
436 if (list_empty(&oobirq_lh)) {
437 brcmf_err("no valid oob irq resource\n");
438 return -ENXIO;
439 }
440
441 oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
442 list);
443
444 sdiodev->irq = oobirq_entry->irq;
445 sdiodev->irq_flags = oobirq_entry->flags;
446 list_del(&oobirq_entry->list);
447 kfree(oobirq_entry);
448
449 return 0;
450}
451#else
452static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
453{
454 return 0;
455}
456#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
457
458static int brcmf_ops_sdio_probe(struct sdio_func *func, 426static int brcmf_ops_sdio_probe(struct sdio_func *func,
459 const struct sdio_device_id *id) 427 const struct sdio_device_id *id)
460{ 428{
@@ -495,15 +463,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
495 dev_set_drvdata(&func->dev, bus_if); 463 dev_set_drvdata(&func->dev, bus_if);
496 dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); 464 dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
497 sdiodev->dev = &sdiodev->func[1]->dev; 465 sdiodev->dev = &sdiodev->func[1]->dev;
466 sdiodev->pdata = brcmfmac_sdio_pdata;
498 467
499 atomic_set(&sdiodev->suspend, false); 468 atomic_set(&sdiodev->suspend, false);
500 init_waitqueue_head(&sdiodev->request_byte_wait); 469 init_waitqueue_head(&sdiodev->request_byte_wait);
501 init_waitqueue_head(&sdiodev->request_word_wait); 470 init_waitqueue_head(&sdiodev->request_word_wait);
502 init_waitqueue_head(&sdiodev->request_chain_wait); 471 init_waitqueue_head(&sdiodev->request_chain_wait);
503 init_waitqueue_head(&sdiodev->request_buffer_wait); 472 init_waitqueue_head(&sdiodev->request_buffer_wait);
504 err = brcmf_sdio_getintrcfg(sdiodev);
505 if (err)
506 goto fail;
507 473
508 brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); 474 brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
509 err = brcmf_sdio_probe(sdiodev); 475 err = brcmf_sdio_probe(sdiodev);
@@ -598,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = {
598static struct sdio_driver brcmf_sdmmc_driver = { 564static struct sdio_driver brcmf_sdmmc_driver = {
599 .probe = brcmf_ops_sdio_probe, 565 .probe = brcmf_ops_sdio_probe,
600 .remove = brcmf_ops_sdio_remove, 566 .remove = brcmf_ops_sdio_remove,
601 .name = "brcmfmac", 567 .name = BRCMFMAC_SDIO_PDATA_NAME,
602 .id_table = brcmf_sdmmc_ids, 568 .id_table = brcmf_sdmmc_ids,
603#ifdef CONFIG_PM_SLEEP 569#ifdef CONFIG_PM_SLEEP
604 .drv = { 570 .drv = {
@@ -607,72 +573,51 @@ static struct sdio_driver brcmf_sdmmc_driver = {
607#endif /* CONFIG_PM_SLEEP */ 573#endif /* CONFIG_PM_SLEEP */
608}; 574};
609 575
610#ifdef CONFIG_BRCMFMAC_SDIO_OOB
611static int brcmf_sdio_pd_probe(struct platform_device *pdev) 576static int brcmf_sdio_pd_probe(struct platform_device *pdev)
612{ 577{
613 struct resource *res; 578 int ret;
614 struct brcmf_sdio_oobirq *oobirq_entry;
615 int i, ret;
616 579
617 INIT_LIST_HEAD(&oobirq_lh); 580 brcmf_dbg(SDIO, "Enter\n");
618 581
619 for (i = 0; ; i++) { 582 brcmfmac_sdio_pdata = pdev->dev.platform_data;
620 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
621 if (!res)
622 break;
623 583
624 oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq), 584 if (brcmfmac_sdio_pdata->power_on)
625 GFP_KERNEL); 585 brcmfmac_sdio_pdata->power_on();
626 if (!oobirq_entry)
627 return -ENOMEM;
628 oobirq_entry->irq = res->start;
629 oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
630 list_add_tail(&oobirq_entry->list, &oobirq_lh);
631 }
632 if (i == 0)
633 return -ENXIO;
634 586
635 ret = sdio_register_driver(&brcmf_sdmmc_driver); 587 ret = sdio_register_driver(&brcmf_sdmmc_driver);
636
637 if (ret) 588 if (ret)
638 brcmf_err("sdio_register_driver failed: %d\n", ret); 589 brcmf_err("sdio_register_driver failed: %d\n", ret);
639 590
640 return ret; 591 return ret;
641} 592}
642 593
643static struct platform_driver brcmf_sdio_pd = { 594static int brcmf_sdio_pd_remove(struct platform_device *pdev)
644 .probe = brcmf_sdio_pd_probe,
645 .driver = {
646 .name = "brcmf_sdio_pd"
647 }
648};
649
650void brcmf_sdio_exit(void)
651{ 595{
652 brcmf_dbg(SDIO, "Enter\n"); 596 brcmf_dbg(SDIO, "Enter\n");
653 597
598 if (brcmfmac_sdio_pdata->power_off)
599 brcmfmac_sdio_pdata->power_off();
600
654 sdio_unregister_driver(&brcmf_sdmmc_driver); 601 sdio_unregister_driver(&brcmf_sdmmc_driver);
655 602
656 platform_driver_unregister(&brcmf_sdio_pd); 603 return 0;
657} 604}
658 605
659void brcmf_sdio_init(void) 606static struct platform_driver brcmf_sdio_pd = {
660{ 607 .remove = brcmf_sdio_pd_remove,
661 int ret; 608 .driver = {
662 609 .name = BRCMFMAC_SDIO_PDATA_NAME
663 brcmf_dbg(SDIO, "Enter\n"); 610 }
664 611};
665 ret = platform_driver_register(&brcmf_sdio_pd);
666 612
667 if (ret)
668 brcmf_err("platform_driver_register failed: %d\n", ret);
669}
670#else
671void brcmf_sdio_exit(void) 613void brcmf_sdio_exit(void)
672{ 614{
673 brcmf_dbg(SDIO, "Enter\n"); 615 brcmf_dbg(SDIO, "Enter\n");
674 616
675 sdio_unregister_driver(&brcmf_sdmmc_driver); 617 if (brcmfmac_sdio_pdata)
618 platform_driver_unregister(&brcmf_sdio_pd);
619 else
620 sdio_unregister_driver(&brcmf_sdmmc_driver);
676} 621}
677 622
678void brcmf_sdio_init(void) 623void brcmf_sdio_init(void)
@@ -681,9 +626,12 @@ void brcmf_sdio_init(void)
681 626
682 brcmf_dbg(SDIO, "Enter\n"); 627 brcmf_dbg(SDIO, "Enter\n");
683 628
684 ret = sdio_register_driver(&brcmf_sdmmc_driver); 629 ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
630 if (ret == -ENODEV) {
631 brcmf_dbg(SDIO, "No platform data available, registering without.\n");
632 ret = sdio_register_driver(&brcmf_sdmmc_driver);
633 }
685 634
686 if (ret) 635 if (ret)
687 brcmf_err("sdio_register_driver failed: %d\n", ret); 636 brcmf_err("driver registration failed: %d\n", ret);
688} 637}
689#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index fd697ce3683c..d2487518bd2a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -31,6 +31,7 @@
31#include <linux/bcma/bcma.h> 31#include <linux/bcma/bcma.h>
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/vmalloc.h> 33#include <linux/vmalloc.h>
34#include <linux/platform_data/brcmfmac-sdio.h>
34#include <asm/unaligned.h> 35#include <asm/unaligned.h>
35#include <defs.h> 36#include <defs.h>
36#include <brcmu_wifi.h> 37#include <brcmu_wifi.h>
@@ -517,7 +518,7 @@ static int qcount[NUMPRIO];
517static int tx_packets[NUMPRIO]; 518static int tx_packets[NUMPRIO];
518#endif /* DEBUG */ 519#endif /* DEBUG */
519 520
520#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ 521#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
521 522
522#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) 523#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
523 524
@@ -2046,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
2046 bus->tx_seq = bus->rx_seq = 0; 2047 bus->tx_seq = bus->rx_seq = 0;
2047} 2048}
2048 2049
2049#ifdef CONFIG_BRCMFMAC_SDIO_OOB
2050static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) 2050static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
2051{ 2051{
2052 unsigned long flags; 2052 unsigned long flags;
2053 2053
2054 spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); 2054 if (bus->sdiodev->oob_irq_requested) {
2055 if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { 2055 spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
2056 enable_irq(bus->sdiodev->irq); 2056 if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
2057 bus->sdiodev->irq_en = true; 2057 enable_irq(bus->sdiodev->pdata->oob_irq_nr);
2058 bus->sdiodev->irq_en = true;
2059 }
2060 spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
2058 } 2061 }
2059 spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
2060}
2061#else
2062static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
2063{
2064} 2062}
2065#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
2066 2063
2067static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) 2064static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
2068{ 2065{
@@ -3639,6 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
3639 int err = 0; 3636 int err = 0;
3640 int reg_addr; 3637 int reg_addr;
3641 u32 reg_val; 3638 u32 reg_val;
3639 u32 drivestrength;
3642 3640
3643 bus->alp_only = true; 3641 bus->alp_only = true;
3644 3642
@@ -3679,8 +3677,11 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
3679 goto fail; 3677 goto fail;
3680 } 3678 }
3681 3679
3682 brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, 3680 if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
3683 SDIO_DRIVE_STRENGTH); 3681 drivestrength = bus->sdiodev->pdata->drive_strength;
3682 else
3683 drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
3684 brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
3684 3685
3685 /* Get info on the SOCRAM cores... */ 3686 /* Get info on the SOCRAM cores... */
3686 bus->ramsize = bus->ci->ramsize; 3687 bus->ramsize = bus->ci->ramsize;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 28ed3cc9f35a..7c1b6332747e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -174,13 +174,11 @@ struct brcmf_sdio_dev {
174 wait_queue_head_t request_buffer_wait; 174 wait_queue_head_t request_buffer_wait;
175 struct device *dev; 175 struct device *dev;
176 struct brcmf_bus *bus_if; 176 struct brcmf_bus *bus_if;
177#ifdef CONFIG_BRCMFMAC_SDIO_OOB 177 struct brcmfmac_sdio_platform_data *pdata;
178 unsigned int irq; /* oob interrupt number */ 178 bool oob_irq_requested;
179 unsigned long irq_flags; /* board specific oob flags */
180 bool irq_en; /* irq enable flags */ 179 bool irq_en; /* irq enable flags */
181 spinlock_t irq_en_lock; 180 spinlock_t irq_en_lock;
182 bool irq_wake; /* irq wake enable flags */ 181 bool irq_wake; /* irq wake enable flags */
183#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
184}; 182};
185 183
186/* Register/deregister interrupt handler. */ 184/* Register/deregister interrupt handler. */