aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c56
-rw-r--r--include/linux/spi/wl12xx.h2
2 files changed, 53 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index 7409c3468e25..d234285c2c81 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -25,6 +25,7 @@
25#include <linux/mmc/sdio_ids.h> 25#include <linux/mmc/sdio_ids.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/spi/wl12xx.h> 27#include <linux/spi/wl12xx.h>
28#include <linux/irq.h>
28 29
29#include "wl1251.h" 30#include "wl1251.h"
30 31
@@ -134,18 +135,36 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl)
134 sdio_release_host(func); 135 sdio_release_host(func);
135} 136}
136 137
138/* Interrupts when using dedicated WLAN_IRQ pin */
139static irqreturn_t wl1251_line_irq(int irq, void *cookie)
140{
141 struct wl1251 *wl = cookie;
142
143 ieee80211_queue_work(wl->hw, &wl->irq_work);
144
145 return IRQ_HANDLED;
146}
147
148static void wl1251_enable_line_irq(struct wl1251 *wl)
149{
150 return enable_irq(wl->irq);
151}
152
153static void wl1251_disable_line_irq(struct wl1251 *wl)
154{
155 return disable_irq(wl->irq);
156}
157
137static void wl1251_sdio_set_power(bool enable) 158static void wl1251_sdio_set_power(bool enable)
138{ 159{
139} 160}
140 161
141static const struct wl1251_if_operations wl1251_sdio_ops = { 162static struct wl1251_if_operations wl1251_sdio_ops = {
142 .read = wl1251_sdio_read, 163 .read = wl1251_sdio_read,
143 .write = wl1251_sdio_write, 164 .write = wl1251_sdio_write,
144 .write_elp = wl1251_sdio_write_elp, 165 .write_elp = wl1251_sdio_write_elp,
145 .read_elp = wl1251_sdio_read_elp, 166 .read_elp = wl1251_sdio_read_elp,
146 .reset = wl1251_sdio_reset, 167 .reset = wl1251_sdio_reset,
147 .enable_irq = wl1251_sdio_enable_irq,
148 .disable_irq = wl1251_sdio_disable_irq,
149}; 168};
150 169
151static int wl1251_platform_probe(struct platform_device *pdev) 170static int wl1251_platform_probe(struct platform_device *pdev)
@@ -191,6 +210,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
191 goto release; 210 goto release;
192 211
193 sdio_set_block_size(func, 512); 212 sdio_set_block_size(func, 512);
213 sdio_release_host(func);
194 214
195 SET_IEEE80211_DEV(hw, &func->dev); 215 SET_IEEE80211_DEV(hw, &func->dev);
196 wl->if_priv = func; 216 wl->if_priv = func;
@@ -199,17 +219,41 @@ static int wl1251_sdio_probe(struct sdio_func *func,
199 219
200 if (wl12xx_board_data != NULL) { 220 if (wl12xx_board_data != NULL) {
201 wl->set_power = wl12xx_board_data->set_power; 221 wl->set_power = wl12xx_board_data->set_power;
222 wl->irq = wl12xx_board_data->irq;
202 wl->use_eeprom = wl12xx_board_data->use_eeprom; 223 wl->use_eeprom = wl12xx_board_data->use_eeprom;
203 } 224 }
204 225
205 sdio_release_host(func); 226 if (wl->irq) {
227 ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
228 if (ret < 0) {
229 wl1251_error("request_irq() failed: %d", ret);
230 goto disable;
231 }
232
233 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
234 disable_irq(wl->irq);
235
236 wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
237 wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
238
239 wl1251_info("using dedicated interrupt line");
240 } else {
241 wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
242 wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
243
244 wl1251_info("using SDIO interrupt");
245 }
246
206 ret = wl1251_init_ieee80211(wl); 247 ret = wl1251_init_ieee80211(wl);
207 if (ret) 248 if (ret)
208 goto disable; 249 goto out_free_irq;
209 250
210 sdio_set_drvdata(func, wl); 251 sdio_set_drvdata(func, wl);
211 return ret; 252 return ret;
212 253
254out_free_irq:
255 if (wl->irq)
256 free_irq(wl->irq, wl);
213disable: 257disable:
214 sdio_claim_host(func); 258 sdio_claim_host(func);
215 sdio_disable_func(func); 259 sdio_disable_func(func);
@@ -222,6 +266,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
222{ 266{
223 struct wl1251 *wl = sdio_get_drvdata(func); 267 struct wl1251 *wl = sdio_get_drvdata(func);
224 268
269 if (wl->irq)
270 free_irq(wl->irq, wl);
225 wl1251_free_hw(wl); 271 wl1251_free_hw(wl);
226 272
227 sdio_claim_host(func); 273 sdio_claim_host(func);
diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h
index aed64ed3dc8a..a223ecbc71ef 100644
--- a/include/linux/spi/wl12xx.h
+++ b/include/linux/spi/wl12xx.h
@@ -26,6 +26,8 @@
26 26
27struct wl12xx_platform_data { 27struct wl12xx_platform_data {
28 void (*set_power)(bool enable); 28 void (*set_power)(bool enable);
29 /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
30 int irq;
29 bool use_eeprom; 31 bool use_eeprom;
30}; 32};
31 33