diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_sdio.c | 56 | ||||
-rw-r--r-- | include/linux/spi/wl12xx.h | 2 |
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 */ | ||
139 | static 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 | |||
148 | static void wl1251_enable_line_irq(struct wl1251 *wl) | ||
149 | { | ||
150 | return enable_irq(wl->irq); | ||
151 | } | ||
152 | |||
153 | static void wl1251_disable_line_irq(struct wl1251 *wl) | ||
154 | { | ||
155 | return disable_irq(wl->irq); | ||
156 | } | ||
157 | |||
137 | static void wl1251_sdio_set_power(bool enable) | 158 | static void wl1251_sdio_set_power(bool enable) |
138 | { | 159 | { |
139 | } | 160 | } |
140 | 161 | ||
141 | static const struct wl1251_if_operations wl1251_sdio_ops = { | 162 | static 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 | ||
151 | static int wl1251_platform_probe(struct platform_device *pdev) | 170 | static 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 | ||
254 | out_free_irq: | ||
255 | if (wl->irq) | ||
256 | free_irq(wl->irq, wl); | ||
213 | disable: | 257 | disable: |
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 | ||
27 | struct wl12xx_platform_data { | 27 | struct 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 | ||