|
@@ -25,6 +25,7 @@
|
|
|
#include <linux/mmc/sdio_ids.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/spi/wl12xx.h>
|
|
|
+#include <linux/irq.h>
|
|
|
|
|
|
#include "wl1251.h"
|
|
|
|
|
@@ -134,18 +135,36 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl)
|
|
|
sdio_release_host(func);
|
|
|
}
|
|
|
|
|
|
+/* Interrupts when using dedicated WLAN_IRQ pin */
|
|
|
+static irqreturn_t wl1251_line_irq(int irq, void *cookie)
|
|
|
+{
|
|
|
+ struct wl1251 *wl = cookie;
|
|
|
+
|
|
|
+ ieee80211_queue_work(wl->hw, &wl->irq_work);
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+static void wl1251_enable_line_irq(struct wl1251 *wl)
|
|
|
+{
|
|
|
+ return enable_irq(wl->irq);
|
|
|
+}
|
|
|
+
|
|
|
+static void wl1251_disable_line_irq(struct wl1251 *wl)
|
|
|
+{
|
|
|
+ return disable_irq(wl->irq);
|
|
|
+}
|
|
|
+
|
|
|
static void wl1251_sdio_set_power(bool enable)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-static const struct wl1251_if_operations wl1251_sdio_ops = {
|
|
|
+static struct wl1251_if_operations wl1251_sdio_ops = {
|
|
|
.read = wl1251_sdio_read,
|
|
|
.write = wl1251_sdio_write,
|
|
|
.write_elp = wl1251_sdio_write_elp,
|
|
|
.read_elp = wl1251_sdio_read_elp,
|
|
|
.reset = wl1251_sdio_reset,
|
|
|
- .enable_irq = wl1251_sdio_enable_irq,
|
|
|
- .disable_irq = wl1251_sdio_disable_irq,
|
|
|
};
|
|
|
|
|
|
static int wl1251_platform_probe(struct platform_device *pdev)
|
|
@@ -191,6 +210,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
|
|
|
goto release;
|
|
|
|
|
|
sdio_set_block_size(func, 512);
|
|
|
+ sdio_release_host(func);
|
|
|
|
|
|
SET_IEEE80211_DEV(hw, &func->dev);
|
|
|
wl->if_priv = func;
|
|
@@ -199,17 +219,41 @@ static int wl1251_sdio_probe(struct sdio_func *func,
|
|
|
|
|
|
if (wl12xx_board_data != NULL) {
|
|
|
wl->set_power = wl12xx_board_data->set_power;
|
|
|
+ wl->irq = wl12xx_board_data->irq;
|
|
|
wl->use_eeprom = wl12xx_board_data->use_eeprom;
|
|
|
}
|
|
|
|
|
|
- sdio_release_host(func);
|
|
|
+ if (wl->irq) {
|
|
|
+ ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
|
|
|
+ if (ret < 0) {
|
|
|
+ wl1251_error("request_irq() failed: %d", ret);
|
|
|
+ goto disable;
|
|
|
+ }
|
|
|
+
|
|
|
+ set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
|
|
|
+ disable_irq(wl->irq);
|
|
|
+
|
|
|
+ wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
|
|
|
+ wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
|
|
|
+
|
|
|
+ wl1251_info("using dedicated interrupt line");
|
|
|
+ } else {
|
|
|
+ wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
|
|
|
+ wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
|
|
|
+
|
|
|
+ wl1251_info("using SDIO interrupt");
|
|
|
+ }
|
|
|
+
|
|
|
ret = wl1251_init_ieee80211(wl);
|
|
|
if (ret)
|
|
|
- goto disable;
|
|
|
+ goto out_free_irq;
|
|
|
|
|
|
sdio_set_drvdata(func, wl);
|
|
|
return ret;
|
|
|
|
|
|
+out_free_irq:
|
|
|
+ if (wl->irq)
|
|
|
+ free_irq(wl->irq, wl);
|
|
|
disable:
|
|
|
sdio_claim_host(func);
|
|
|
sdio_disable_func(func);
|
|
@@ -222,6 +266,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
|
|
|
{
|
|
|
struct wl1251 *wl = sdio_get_drvdata(func);
|
|
|
|
|
|
+ if (wl->irq)
|
|
|
+ free_irq(wl->irq, wl);
|
|
|
wl1251_free_hw(wl);
|
|
|
|
|
|
sdio_claim_host(func);
|