aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrazvydas Ignotas <notasas@gmail.com>2010-04-16 06:22:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-16 15:47:14 -0400
commita02a2956809d88b42b9a1f8003d60a343353b5ea (patch)
tree58f3375f5b8c54ca68ca32ae30b705e11c2457af
parent7f1f5a0060e377ff6a15903487b39223e12b8568 (diff)
wl1251: add support for dedicated IRQ line
wl1251 has WLAN_IRQ pin for generating interrupts to host processor, which is mandatory in SPI mode and optional in SDIO mode (which can use SDIO interrupts instead). However TI recommends using deditated IRQ line for SDIO too. Add support for using dedicated interrupt line with SDIO, but also leave ability to switch to SDIO interrupts in case it's needed. Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Reviewed-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-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