aboutsummaryrefslogtreecommitdiffstats
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
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>
-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
-rw-r--r--include/linux/platform_data/brcmfmac-sdio.h124
6 files changed, 250 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);