blob: 094176e92ebe6f5ecda038e9e6f22ef1824c787a [file] [log] [blame]
Pierre Ossman727c26e2007-10-17 22:24:24 +02001/*
2 * linux/drivers/net/wireless/libertas/if_sdio.c
3 *
Pierre Ossmanad3868b2008-06-28 12:52:45 +02004 * Copyright 2007-2008 Pierre Ossman
Pierre Ossman727c26e2007-10-17 22:24:24 +02005 *
6 * Inspired by if_cs.c, Copyright 2007 Holger Schurig
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This hardware has more or less no CMD53 support, so all registers
14 * must be accessed using sdio_readb()/sdio_writeb().
15 *
16 * Transfers must be in one transaction or the firmware goes bonkers.
17 * This means that the transfer must either be small enough to do a
18 * byte based transfer or it must be padded to a multiple of the
19 * current block size.
20 *
21 * As SDIO is still new to the kernel, it is unfortunately common with
David Woodhouse7e226272007-12-14 22:53:41 -050022 * bugs in the host controllers related to that. One such bug is that
Pierre Ossman727c26e2007-10-17 22:24:24 +020023 * controllers cannot do transfers that aren't a multiple of 4 bytes.
24 * If you don't have time to fix the host controller driver, you can
25 * work around the problem by modifying if_sdio_host_to_card() and
26 * if_sdio_card_to_host() to pad the data.
27 */
28
Ilpo Järvinen23827922008-12-13 21:33:13 +020029#include <linux/kernel.h>
Pierre Ossman727c26e2007-10-17 22:24:24 +020030#include <linux/moduleparam.h>
31#include <linux/firmware.h>
32#include <linux/netdevice.h>
33#include <linux/delay.h>
34#include <linux/mmc/card.h>
35#include <linux/mmc/sdio_func.h>
36#include <linux/mmc/sdio_ids.h>
Daniel Mack8a64c0f2010-04-06 10:52:44 +020037#include <linux/mmc/sdio.h>
38#include <linux/mmc/host.h>
Pierre Ossman727c26e2007-10-17 22:24:24 +020039
40#include "host.h"
41#include "decl.h"
42#include "defs.h"
43#include "dev.h"
Bing Zhao6bc61f42009-06-01 18:04:36 -070044#include "cmd.h"
Pierre Ossman727c26e2007-10-17 22:24:24 +020045#include "if_sdio.h"
46
Bing Zhao6bc61f42009-06-01 18:04:36 -070047/* The if_sdio_remove() callback function is called when
48 * user removes this module from kernel space or ejects
49 * the card from the slot. The driver handles these 2 cases
50 * differently for SD8688 combo chip.
51 * If the user is removing the module, the FUNC_SHUTDOWN
52 * command for SD8688 is sent to the firmware.
53 * If the card is removed, there is no need to send this command.
54 *
55 * The variable 'user_rmmod' is used to distinguish these two
56 * scenarios. This flag is initialized as FALSE in case the card
57 * is removed, and will be set to TRUE for module removal when
58 * module_exit function is called.
59 */
60static u8 user_rmmod;
61
Holger Schurig10078322007-11-15 18:05:47 -050062static char *lbs_helper_name = NULL;
63module_param_named(helper_name, lbs_helper_name, charp, 0644);
Pierre Ossman727c26e2007-10-17 22:24:24 +020064
Holger Schurig10078322007-11-15 18:05:47 -050065static char *lbs_fw_name = NULL;
66module_param_named(fw_name, lbs_fw_name, charp, 0644);
Pierre Ossman727c26e2007-10-17 22:24:24 +020067
68static const struct sdio_device_id if_sdio_ids[] = {
Bing Zhaoe45d8e52009-04-06 15:50:56 -070069 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
70 SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
71 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
72 SDIO_DEVICE_ID_MARVELL_8688WLAN) },
73 { /* end: all zeroes */ },
Pierre Ossman727c26e2007-10-17 22:24:24 +020074};
75
76MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
77
78struct if_sdio_model {
79 int model;
80 const char *helper;
81 const char *firmware;
82};
83
84static struct if_sdio_model if_sdio_models[] = {
85 {
86 /* 8385 */
Bing Zhaoe70a5ac2009-05-19 19:48:18 -070087 .model = IF_SDIO_MODEL_8385,
Pierre Ossman727c26e2007-10-17 22:24:24 +020088 .helper = "sd8385_helper.bin",
89 .firmware = "sd8385.bin",
90 },
91 {
92 /* 8686 */
Bing Zhaoe70a5ac2009-05-19 19:48:18 -070093 .model = IF_SDIO_MODEL_8686,
Pierre Ossman727c26e2007-10-17 22:24:24 +020094 .helper = "sd8686_helper.bin",
95 .firmware = "sd8686.bin",
96 },
Bing Zhaoe45d8e52009-04-06 15:50:56 -070097 {
98 /* 8688 */
Bing Zhaoe70a5ac2009-05-19 19:48:18 -070099 .model = IF_SDIO_MODEL_8688,
Bing Zhaoe45d8e52009-04-06 15:50:56 -0700100 .helper = "sd8688_helper.bin",
101 .firmware = "sd8688.bin",
102 },
Pierre Ossman727c26e2007-10-17 22:24:24 +0200103};
Ben Hutchingsa974a4b2009-11-07 22:00:03 +0000104MODULE_FIRMWARE("sd8385_helper.bin");
105MODULE_FIRMWARE("sd8385.bin");
106MODULE_FIRMWARE("sd8686_helper.bin");
107MODULE_FIRMWARE("sd8686.bin");
108MODULE_FIRMWARE("sd8688_helper.bin");
109MODULE_FIRMWARE("sd8688.bin");
Pierre Ossman727c26e2007-10-17 22:24:24 +0200110
111struct if_sdio_packet {
112 struct if_sdio_packet *next;
113 u16 nb;
114 u8 buffer[0] __attribute__((aligned(4)));
115};
116
117struct if_sdio_card {
118 struct sdio_func *func;
Holger Schurig69f90322007-11-23 15:43:44 +0100119 struct lbs_private *priv;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200120
121 int model;
122 unsigned long ioport;
Bing Zhao2c7e5792009-05-21 11:32:34 -0700123 unsigned int scratch_reg;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200124
125 const char *helper;
126 const char *firmware;
127
128 u8 buffer[65536];
Pierre Ossman727c26e2007-10-17 22:24:24 +0200129
130 spinlock_t lock;
131 struct if_sdio_packet *packets;
Dan Williams9b02f412009-02-20 12:27:38 -0500132
133 struct workqueue_struct *workqueue;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200134 struct work_struct packet_worker;
Bing Zhaob136a142009-05-19 19:48:19 -0700135
136 u8 rx_unit;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200137};
138
139/********************************************************************/
140/* I/O */
141/********************************************************************/
142
Bing Zhao2c7e5792009-05-21 11:32:34 -0700143/*
144 * For SD8385/SD8686, this function reads firmware status after
145 * the image is downloaded, or reads RX packet length when
146 * interrupt (with IF_SDIO_H_INT_UPLD bit set) is received.
147 * For SD8688, this function reads firmware status only.
148 */
Pierre Ossman727c26e2007-10-17 22:24:24 +0200149static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
150{
Bing Zhao2c7e5792009-05-21 11:32:34 -0700151 int ret;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200152 u16 scratch;
153
Bing Zhao2c7e5792009-05-21 11:32:34 -0700154 scratch = sdio_readb(card->func, card->scratch_reg, &ret);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200155 if (!ret)
Bing Zhao2c7e5792009-05-21 11:32:34 -0700156 scratch |= sdio_readb(card->func, card->scratch_reg + 1,
157 &ret) << 8;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200158
159 if (err)
160 *err = ret;
161
162 if (ret)
163 return 0xffff;
164
165 return scratch;
166}
167
Bing Zhaob136a142009-05-19 19:48:19 -0700168static u8 if_sdio_read_rx_unit(struct if_sdio_card *card)
169{
170 int ret;
171 u8 rx_unit;
172
173 rx_unit = sdio_readb(card->func, IF_SDIO_RX_UNIT, &ret);
174
175 if (ret)
176 rx_unit = 0;
177
178 return rx_unit;
179}
180
181static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)
182{
183 int ret;
184 u16 rx_len;
185
186 switch (card->model) {
187 case IF_SDIO_MODEL_8385:
188 case IF_SDIO_MODEL_8686:
189 rx_len = if_sdio_read_scratch(card, &ret);
190 break;
191 case IF_SDIO_MODEL_8688:
192 default: /* for newer chipsets */
193 rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
194 if (!ret)
195 rx_len <<= card->rx_unit;
196 else
197 rx_len = 0xffff; /* invalid length */
198
199 break;
200 }
201
202 if (err)
203 *err = ret;
204
205 return rx_len;
206}
207
Pierre Ossman727c26e2007-10-17 22:24:24 +0200208static int if_sdio_handle_cmd(struct if_sdio_card *card,
209 u8 *buffer, unsigned size)
210{
Holger Schurig7919b892008-04-01 14:50:43 +0200211 struct lbs_private *priv = card->priv;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200212 int ret;
213 unsigned long flags;
Holger Schurig7919b892008-04-01 14:50:43 +0200214 u8 i;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200215
216 lbs_deb_enter(LBS_DEB_SDIO);
217
Dan Williamsddac4522007-12-11 13:49:39 -0500218 if (size > LBS_CMD_BUFFER_SIZE) {
Pierre Ossman727c26e2007-10-17 22:24:24 +0200219 lbs_deb_sdio("response packet too large (%d bytes)\n",
220 (int)size);
221 ret = -E2BIG;
222 goto out;
223 }
224
Holger Schurig7919b892008-04-01 14:50:43 +0200225 spin_lock_irqsave(&priv->driver_lock, flags);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200226
Holger Schurig7919b892008-04-01 14:50:43 +0200227 i = (priv->resp_idx == 0) ? 1 : 0;
228 BUG_ON(priv->resp_len[i]);
229 priv->resp_len[i] = size;
230 memcpy(priv->resp_buf[i], buffer, size);
231 lbs_notify_command_response(priv, i);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200232
Holger Schurig7919b892008-04-01 14:50:43 +0200233 spin_unlock_irqrestore(&card->priv->driver_lock, flags);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200234
235 ret = 0;
236
237out:
Pierre Ossman727c26e2007-10-17 22:24:24 +0200238 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200239 return ret;
240}
241
242static int if_sdio_handle_data(struct if_sdio_card *card,
243 u8 *buffer, unsigned size)
244{
245 int ret;
246 struct sk_buff *skb;
247 char *data;
248
249 lbs_deb_enter(LBS_DEB_SDIO);
250
251 if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
252 lbs_deb_sdio("response packet too large (%d bytes)\n",
253 (int)size);
254 ret = -E2BIG;
255 goto out;
256 }
257
Pierre Ossman51e6b712007-10-22 19:05:32 +0200258 skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200259 if (!skb) {
260 ret = -ENOMEM;
261 goto out;
262 }
263
Pierre Ossman51e6b712007-10-22 19:05:32 +0200264 skb_reserve(skb, NET_IP_ALIGN);
265
Pierre Ossman727c26e2007-10-17 22:24:24 +0200266 data = skb_put(skb, size);
267
268 memcpy(data, buffer, size);
269
Holger Schurig10078322007-11-15 18:05:47 -0500270 lbs_process_rxed_packet(card->priv, skb);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200271
272 ret = 0;
273
274out:
275 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
276
277 return ret;
278}
279
280static int if_sdio_handle_event(struct if_sdio_card *card,
281 u8 *buffer, unsigned size)
282{
283 int ret;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200284 u32 event;
285
286 lbs_deb_enter(LBS_DEB_SDIO);
287
Bing Zhaoe70a5ac2009-05-19 19:48:18 -0700288 if (card->model == IF_SDIO_MODEL_8385) {
Pierre Ossman727c26e2007-10-17 22:24:24 +0200289 event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
290 if (ret)
291 goto out;
Bing Zhaof5ac2b92009-02-04 22:22:39 -0800292
293 /* right shift 3 bits to get the event id */
294 event >>= 3;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200295 } else {
296 if (size < 4) {
297 lbs_deb_sdio("event packet too small (%d bytes)\n",
298 (int)size);
299 ret = -EINVAL;
300 goto out;
301 }
302 event = buffer[3] << 24;
303 event |= buffer[2] << 16;
304 event |= buffer[1] << 8;
305 event |= buffer[0] << 0;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200306 }
307
Holger Schurig7919b892008-04-01 14:50:43 +0200308 lbs_queue_event(card->priv, event & 0xFF);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200309 ret = 0;
310
311out:
312 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
313
314 return ret;
315}
316
Dan Williams96021f02010-04-15 13:27:44 -0700317static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition)
318{
319 u8 status;
320 unsigned long timeout;
321 int ret = 0;
322
323 timeout = jiffies + HZ;
324 while (1) {
325 status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
Dan Williamsca9625572010-04-28 12:37:46 -0700326 if (ret)
327 return ret;
328 if ((status & condition) == condition)
Dan Williams96021f02010-04-15 13:27:44 -0700329 break;
330 if (time_after(jiffies, timeout))
331 return -ETIMEDOUT;
332 mdelay(1);
333 }
334 return ret;
335}
336
Pierre Ossman727c26e2007-10-17 22:24:24 +0200337static int if_sdio_card_to_host(struct if_sdio_card *card)
338{
339 int ret;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200340 u16 size, type, chunk;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200341
342 lbs_deb_enter(LBS_DEB_SDIO);
343
Bing Zhaob136a142009-05-19 19:48:19 -0700344 size = if_sdio_read_rx_len(card, &ret);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200345 if (ret)
346 goto out;
347
348 if (size < 4) {
349 lbs_deb_sdio("invalid packet size (%d bytes) from firmware\n",
350 (int)size);
351 ret = -EINVAL;
352 goto out;
353 }
354
Dan Williams96021f02010-04-15 13:27:44 -0700355 ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
356 if (ret)
357 goto out;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200358
359 /*
360 * The transfer must be in one transaction or the firmware
Pierre Ossmanad3868b2008-06-28 12:52:45 +0200361 * goes suicidal. There's no way to guarantee that for all
362 * controllers, but we can at least try.
Pierre Ossman727c26e2007-10-17 22:24:24 +0200363 */
Pierre Ossmanad3868b2008-06-28 12:52:45 +0200364 chunk = sdio_align_size(card->func, size);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200365
366 ret = sdio_readsb(card->func, card->buffer, card->ioport, chunk);
367 if (ret)
368 goto out;
369
370 chunk = card->buffer[0] | (card->buffer[1] << 8);
371 type = card->buffer[2] | (card->buffer[3] << 8);
372
373 lbs_deb_sdio("packet of type %d and size %d bytes\n",
374 (int)type, (int)chunk);
375
376 if (chunk > size) {
377 lbs_deb_sdio("packet fragment (%d > %d)\n",
378 (int)chunk, (int)size);
379 ret = -EINVAL;
380 goto out;
381 }
382
383 if (chunk < size) {
384 lbs_deb_sdio("packet fragment (%d < %d)\n",
385 (int)chunk, (int)size);
386 }
387
388 switch (type) {
389 case MVMS_CMD:
390 ret = if_sdio_handle_cmd(card, card->buffer + 4, chunk - 4);
391 if (ret)
392 goto out;
393 break;
394 case MVMS_DAT:
395 ret = if_sdio_handle_data(card, card->buffer + 4, chunk - 4);
396 if (ret)
397 goto out;
398 break;
399 case MVMS_EVENT:
400 ret = if_sdio_handle_event(card, card->buffer + 4, chunk - 4);
401 if (ret)
402 goto out;
403 break;
404 default:
405 lbs_deb_sdio("invalid type (%d) from firmware\n",
406 (int)type);
407 ret = -EINVAL;
408 goto out;
409 }
410
411out:
412 if (ret)
413 lbs_pr_err("problem fetching packet from firmware\n");
414
415 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
416
417 return ret;
418}
419
420static void if_sdio_host_to_card_worker(struct work_struct *work)
421{
422 struct if_sdio_card *card;
423 struct if_sdio_packet *packet;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200424 int ret;
425 unsigned long flags;
426
427 lbs_deb_enter(LBS_DEB_SDIO);
428
429 card = container_of(work, struct if_sdio_card, packet_worker);
430
431 while (1) {
432 spin_lock_irqsave(&card->lock, flags);
433 packet = card->packets;
434 if (packet)
435 card->packets = packet->next;
436 spin_unlock_irqrestore(&card->lock, flags);
437
438 if (!packet)
439 break;
440
441 sdio_claim_host(card->func);
442
Dan Williams96021f02010-04-15 13:27:44 -0700443 ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
444 if (ret == 0) {
445 ret = sdio_writesb(card->func, card->ioport,
446 packet->buffer, packet->nb);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200447 }
448
Pierre Ossman727c26e2007-10-17 22:24:24 +0200449 if (ret)
Dan Williams96021f02010-04-15 13:27:44 -0700450 lbs_pr_err("error %d sending packet to firmware\n", ret);
451
Pierre Ossman727c26e2007-10-17 22:24:24 +0200452 sdio_release_host(card->func);
453
454 kfree(packet);
455 }
456
457 lbs_deb_leave(LBS_DEB_SDIO);
458}
459
460/********************************************************************/
461/* Firmware */
462/********************************************************************/
463
Dan Williams96021f02010-04-15 13:27:44 -0700464#define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
465
Pierre Ossman727c26e2007-10-17 22:24:24 +0200466static int if_sdio_prog_helper(struct if_sdio_card *card)
467{
468 int ret;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200469 const struct firmware *fw;
470 unsigned long timeout;
471 u8 *chunk_buffer;
472 u32 chunk_size;
David Woodhouse6dfff892008-05-23 18:37:51 +0100473 const u8 *firmware;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200474 size_t size;
475
476 lbs_deb_enter(LBS_DEB_SDIO);
477
478 ret = request_firmware(&fw, card->helper, &card->func->dev);
479 if (ret) {
480 lbs_pr_err("can't load helper firmware\n");
481 goto out;
482 }
483
484 chunk_buffer = kzalloc(64, GFP_KERNEL);
485 if (!chunk_buffer) {
486 ret = -ENOMEM;
487 goto release_fw;
488 }
489
490 sdio_claim_host(card->func);
491
492 ret = sdio_set_block_size(card->func, 32);
493 if (ret)
494 goto release;
495
496 firmware = fw->data;
497 size = fw->size;
498
499 while (size) {
Dan Williams96021f02010-04-15 13:27:44 -0700500 ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
501 if (ret)
502 goto release;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200503
Dan Williamsac1a4742010-04-15 13:32:58 -0700504 /* On some platforms (like Davinci) the chip needs more time
505 * between helper blocks.
506 */
507 mdelay(2);
508
Pierre Ossman727c26e2007-10-17 22:24:24 +0200509 chunk_size = min(size, (size_t)60);
510
Holger Schurigc2df2ef2007-12-07 15:30:44 +0000511 *((__le32*)chunk_buffer) = cpu_to_le32(chunk_size);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200512 memcpy(chunk_buffer + 4, firmware, chunk_size);
513/*
514 lbs_deb_sdio("sending %d bytes chunk\n", chunk_size);
515*/
516 ret = sdio_writesb(card->func, card->ioport,
517 chunk_buffer, 64);
518 if (ret)
519 goto release;
520
521 firmware += chunk_size;
522 size -= chunk_size;
523 }
524
525 /* an empty block marks the end of the transfer */
526 memset(chunk_buffer, 0, 4);
527 ret = sdio_writesb(card->func, card->ioport, chunk_buffer, 64);
528 if (ret)
529 goto release;
530
531 lbs_deb_sdio("waiting for helper to boot...\n");
532
533 /* wait for the helper to boot by looking at the size register */
534 timeout = jiffies + HZ;
535 while (1) {
536 u16 req_size;
537
538 req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
539 if (ret)
540 goto release;
541
542 req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
543 if (ret)
544 goto release;
545
546 if (req_size != 0)
547 break;
548
549 if (time_after(jiffies, timeout)) {
550 ret = -ETIMEDOUT;
551 goto release;
552 }
553
554 msleep(10);
555 }
556
557 ret = 0;
558
559release:
Pierre Ossman727c26e2007-10-17 22:24:24 +0200560 sdio_release_host(card->func);
561 kfree(chunk_buffer);
562release_fw:
563 release_firmware(fw);
564
565out:
566 if (ret)
567 lbs_pr_err("failed to load helper firmware\n");
568
569 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
570
571 return ret;
572}
573
574static int if_sdio_prog_real(struct if_sdio_card *card)
575{
576 int ret;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200577 const struct firmware *fw;
578 unsigned long timeout;
579 u8 *chunk_buffer;
580 u32 chunk_size;
David Woodhouse6dfff892008-05-23 18:37:51 +0100581 const u8 *firmware;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200582 size_t size, req_size;
583
584 lbs_deb_enter(LBS_DEB_SDIO);
585
586 ret = request_firmware(&fw, card->firmware, &card->func->dev);
587 if (ret) {
588 lbs_pr_err("can't load firmware\n");
589 goto out;
590 }
591
592 chunk_buffer = kzalloc(512, GFP_KERNEL);
593 if (!chunk_buffer) {
594 ret = -ENOMEM;
595 goto release_fw;
596 }
597
598 sdio_claim_host(card->func);
599
600 ret = sdio_set_block_size(card->func, 32);
601 if (ret)
602 goto release;
603
604 firmware = fw->data;
605 size = fw->size;
606
607 while (size) {
Dan Williams96021f02010-04-15 13:27:44 -0700608 ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
609 if (ret)
610 goto release;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200611
612 req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
613 if (ret)
614 goto release;
615
616 req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
617 if (ret)
618 goto release;
619/*
620 lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size);
621*/
622 if (req_size == 0) {
623 lbs_deb_sdio("firmware helper gave up early\n");
624 ret = -EIO;
625 goto release;
626 }
627
628 if (req_size & 0x01) {
629 lbs_deb_sdio("firmware helper signalled error\n");
630 ret = -EIO;
631 goto release;
632 }
633
634 if (req_size > size)
635 req_size = size;
636
637 while (req_size) {
638 chunk_size = min(req_size, (size_t)512);
639
640 memcpy(chunk_buffer, firmware, chunk_size);
641/*
642 lbs_deb_sdio("sending %d bytes (%d bytes) chunk\n",
643 chunk_size, (chunk_size + 31) / 32 * 32);
644*/
645 ret = sdio_writesb(card->func, card->ioport,
Ilpo Järvinen23827922008-12-13 21:33:13 +0200646 chunk_buffer, roundup(chunk_size, 32));
Pierre Ossman727c26e2007-10-17 22:24:24 +0200647 if (ret)
648 goto release;
649
650 firmware += chunk_size;
651 size -= chunk_size;
652 req_size -= chunk_size;
653 }
654 }
655
656 ret = 0;
657
658 lbs_deb_sdio("waiting for firmware to boot...\n");
659
660 /* wait for the firmware to boot */
661 timeout = jiffies + HZ;
662 while (1) {
663 u16 scratch;
664
665 scratch = if_sdio_read_scratch(card, &ret);
666 if (ret)
667 goto release;
668
669 if (scratch == IF_SDIO_FIRMWARE_OK)
670 break;
671
672 if (time_after(jiffies, timeout)) {
673 ret = -ETIMEDOUT;
674 goto release;
675 }
676
677 msleep(10);
678 }
679
680 ret = 0;
681
682release:
Pierre Ossman727c26e2007-10-17 22:24:24 +0200683 sdio_release_host(card->func);
684 kfree(chunk_buffer);
685release_fw:
686 release_firmware(fw);
687
688out:
689 if (ret)
690 lbs_pr_err("failed to load firmware\n");
691
692 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
693
694 return ret;
695}
696
697static int if_sdio_prog_firmware(struct if_sdio_card *card)
698{
699 int ret;
700 u16 scratch;
701
702 lbs_deb_enter(LBS_DEB_SDIO);
703
704 sdio_claim_host(card->func);
705 scratch = if_sdio_read_scratch(card, &ret);
706 sdio_release_host(card->func);
707
708 if (ret)
709 goto out;
710
Bing Zhao2c7e5792009-05-21 11:32:34 -0700711 lbs_deb_sdio("firmware status = %#x\n", scratch);
712
Pierre Ossman727c26e2007-10-17 22:24:24 +0200713 if (scratch == IF_SDIO_FIRMWARE_OK) {
714 lbs_deb_sdio("firmware already loaded\n");
715 goto success;
716 }
717
718 ret = if_sdio_prog_helper(card);
719 if (ret)
720 goto out;
721
722 ret = if_sdio_prog_real(card);
723 if (ret)
724 goto out;
725
726success:
Bing Zhaod26285f82009-05-19 19:48:20 -0700727 sdio_claim_host(card->func);
728 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
729 sdio_release_host(card->func);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200730 ret = 0;
731
732out:
733 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
734
735 return ret;
736}
737
738/*******************************************************************/
739/* Libertas callbacks */
740/*******************************************************************/
741
Holger Schurig69f90322007-11-23 15:43:44 +0100742static int if_sdio_host_to_card(struct lbs_private *priv,
743 u8 type, u8 *buf, u16 nb)
Pierre Ossman727c26e2007-10-17 22:24:24 +0200744{
745 int ret;
746 struct if_sdio_card *card;
747 struct if_sdio_packet *packet, *cur;
748 u16 size;
749 unsigned long flags;
750
751 lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb);
752
753 card = priv->card;
754
755 if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) {
756 ret = -EINVAL;
757 goto out;
758 }
759
760 /*
761 * The transfer must be in one transaction or the firmware
Pierre Ossmanad3868b2008-06-28 12:52:45 +0200762 * goes suicidal. There's no way to guarantee that for all
763 * controllers, but we can at least try.
Pierre Ossman727c26e2007-10-17 22:24:24 +0200764 */
Pierre Ossmanad3868b2008-06-28 12:52:45 +0200765 size = sdio_align_size(card->func, nb + 4);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200766
767 packet = kzalloc(sizeof(struct if_sdio_packet) + size,
768 GFP_ATOMIC);
769 if (!packet) {
770 ret = -ENOMEM;
771 goto out;
772 }
773
774 packet->next = NULL;
775 packet->nb = size;
776
777 /*
778 * SDIO specific header.
779 */
780 packet->buffer[0] = (nb + 4) & 0xff;
781 packet->buffer[1] = ((nb + 4) >> 8) & 0xff;
782 packet->buffer[2] = type;
783 packet->buffer[3] = 0;
784
785 memcpy(packet->buffer + 4, buf, nb);
786
787 spin_lock_irqsave(&card->lock, flags);
788
789 if (!card->packets)
790 card->packets = packet;
791 else {
792 cur = card->packets;
793 while (cur->next)
794 cur = cur->next;
795 cur->next = packet;
796 }
797
798 switch (type) {
799 case MVMS_CMD:
800 priv->dnld_sent = DNLD_CMD_SENT;
801 break;
802 case MVMS_DAT:
803 priv->dnld_sent = DNLD_DATA_SENT;
804 break;
805 default:
806 lbs_deb_sdio("unknown packet type %d\n", (int)type);
807 }
808
809 spin_unlock_irqrestore(&card->lock, flags);
810
Dan Williams9b02f412009-02-20 12:27:38 -0500811 queue_work(card->workqueue, &card->packet_worker);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200812
813 ret = 0;
814
815out:
816 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
817
818 return ret;
819}
820
Amitkumar Karwar49125452009-09-30 20:04:38 -0700821static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
822{
823 int ret = -1;
824 struct cmd_header cmd;
825
826 memset(&cmd, 0, sizeof(cmd));
827
828 lbs_deb_sdio("send DEEP_SLEEP command\n");
829 ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
830 lbs_cmd_copyback, (unsigned long) &cmd);
831 if (ret)
832 lbs_pr_err("DEEP_SLEEP cmd failed\n");
833
834 mdelay(200);
835 return ret;
836}
837
838static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
839{
840 struct if_sdio_card *card = priv->card;
841 int ret = -1;
842
843 lbs_deb_enter(LBS_DEB_SDIO);
844 sdio_claim_host(card->func);
845
846 sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
847 if (ret)
848 lbs_pr_err("sdio_writeb failed!\n");
849
850 sdio_release_host(card->func);
851 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
852 return ret;
853}
854
855static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
856{
857 struct if_sdio_card *card = priv->card;
858 int ret = -1;
859
860 lbs_deb_enter(LBS_DEB_SDIO);
861 sdio_claim_host(card->func);
862
863 sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
864 if (ret)
865 lbs_pr_err("sdio_writeb failed!\n");
866
867 sdio_release_host(card->func);
868 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
869 return ret;
870
871}
872
Pierre Ossman727c26e2007-10-17 22:24:24 +0200873/*******************************************************************/
874/* SDIO callbacks */
875/*******************************************************************/
876
877static void if_sdio_interrupt(struct sdio_func *func)
878{
879 int ret;
880 struct if_sdio_card *card;
881 u8 cause;
882
883 lbs_deb_enter(LBS_DEB_SDIO);
884
885 card = sdio_get_drvdata(func);
886
887 cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
888 if (ret)
889 goto out;
890
891 lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
892
893 sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
894 if (ret)
895 goto out;
896
897 /*
898 * Ignore the define name, this really means the card has
899 * successfully received the command.
900 */
Amitkumar Karwar49125452009-09-30 20:04:38 -0700901 card->priv->is_activity_detected = 1;
David Woodhousee775ed72007-12-06 14:36:11 +0000902 if (cause & IF_SDIO_H_INT_DNLD)
903 lbs_host_to_card_done(card->priv);
904
Pierre Ossman727c26e2007-10-17 22:24:24 +0200905
906 if (cause & IF_SDIO_H_INT_UPLD) {
907 ret = if_sdio_card_to_host(card);
908 if (ret)
909 goto out;
910 }
911
912 ret = 0;
913
914out:
915 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
916}
917
918static int if_sdio_probe(struct sdio_func *func,
919 const struct sdio_device_id *id)
920{
921 struct if_sdio_card *card;
Holger Schurig69f90322007-11-23 15:43:44 +0100922 struct lbs_private *priv;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200923 int ret, i;
924 unsigned int model;
925 struct if_sdio_packet *packet;
Daniel Mack8a64c0f2010-04-06 10:52:44 +0200926 struct mmc_host *host = func->card->host;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200927
928 lbs_deb_enter(LBS_DEB_SDIO);
929
930 for (i = 0;i < func->card->num_info;i++) {
931 if (sscanf(func->card->info[i],
932 "802.11 SDIO ID: %x", &model) == 1)
933 break;
934 if (sscanf(func->card->info[i],
935 "ID: %x", &model) == 1)
936 break;
Bing Zhaoe70a5ac2009-05-19 19:48:18 -0700937 if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
938 model = IF_SDIO_MODEL_8385;
939 break;
940 }
Pierre Ossman727c26e2007-10-17 22:24:24 +0200941 }
942
943 if (i == func->card->num_info) {
944 lbs_pr_err("unable to identify card model\n");
945 return -ENODEV;
946 }
947
948 card = kzalloc(sizeof(struct if_sdio_card), GFP_KERNEL);
949 if (!card)
950 return -ENOMEM;
951
952 card->func = func;
953 card->model = model;
Bing Zhao2c7e5792009-05-21 11:32:34 -0700954
955 switch (card->model) {
956 case IF_SDIO_MODEL_8385:
957 card->scratch_reg = IF_SDIO_SCRATCH_OLD;
958 break;
959 case IF_SDIO_MODEL_8686:
960 card->scratch_reg = IF_SDIO_SCRATCH;
961 break;
962 case IF_SDIO_MODEL_8688:
963 default: /* for newer chipsets */
964 card->scratch_reg = IF_SDIO_FW_STATUS;
965 break;
966 }
967
Pierre Ossman727c26e2007-10-17 22:24:24 +0200968 spin_lock_init(&card->lock);
Dan Williams9b02f412009-02-20 12:27:38 -0500969 card->workqueue = create_workqueue("libertas_sdio");
Pierre Ossman727c26e2007-10-17 22:24:24 +0200970 INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
971
972 for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
973 if (card->model == if_sdio_models[i].model)
974 break;
975 }
976
977 if (i == ARRAY_SIZE(if_sdio_models)) {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200978 lbs_pr_err("unknown card model 0x%x\n", card->model);
Pierre Ossman727c26e2007-10-17 22:24:24 +0200979 ret = -ENODEV;
980 goto free;
981 }
982
983 card->helper = if_sdio_models[i].helper;
984 card->firmware = if_sdio_models[i].firmware;
985
Holger Schurig10078322007-11-15 18:05:47 -0500986 if (lbs_helper_name) {
Pierre Ossman727c26e2007-10-17 22:24:24 +0200987 lbs_deb_sdio("overriding helper firmware: %s\n",
Holger Schurig10078322007-11-15 18:05:47 -0500988 lbs_helper_name);
989 card->helper = lbs_helper_name;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200990 }
991
Holger Schurig10078322007-11-15 18:05:47 -0500992 if (lbs_fw_name) {
993 lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
994 card->firmware = lbs_fw_name;
Pierre Ossman727c26e2007-10-17 22:24:24 +0200995 }
996
997 sdio_claim_host(func);
998
999 ret = sdio_enable_func(func);
1000 if (ret)
1001 goto release;
1002
1003 ret = sdio_claim_irq(func, if_sdio_interrupt);
1004 if (ret)
1005 goto disable;
1006
Daniel Mack8a64c0f2010-04-06 10:52:44 +02001007 /* For 1-bit transfers to the 8686 model, we need to enable the
1008 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
1009 * bit to allow access to non-vendor registers. */
1010 if ((card->model == IF_SDIO_MODEL_8686) &&
1011 (host->caps & MMC_CAP_SDIO_IRQ) &&
1012 (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
1013 u8 reg;
1014
1015 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
1016 reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
1017 if (ret)
1018 goto release_int;
1019
1020 reg |= SDIO_BUS_ECSI;
1021 sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
1022 if (ret)
1023 goto release_int;
1024 }
1025
Pierre Ossman727c26e2007-10-17 22:24:24 +02001026 card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
1027 if (ret)
1028 goto release_int;
1029
1030 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
1031 if (ret)
1032 goto release_int;
1033
1034 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
1035 if (ret)
1036 goto release_int;
1037
1038 sdio_release_host(func);
1039
1040 sdio_set_drvdata(func, card);
1041
1042 lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
1043 "device = 0x%X, model = 0x%X, ioport = 0x%X\n",
1044 func->class, func->vendor, func->device,
1045 model, (unsigned)card->ioport);
1046
1047 ret = if_sdio_prog_firmware(card);
1048 if (ret)
1049 goto reclaim;
1050
Holger Schurig10078322007-11-15 18:05:47 -05001051 priv = lbs_add_card(card, &func->dev);
Pierre Ossman727c26e2007-10-17 22:24:24 +02001052 if (!priv) {
1053 ret = -ENOMEM;
1054 goto reclaim;
1055 }
1056
1057 card->priv = priv;
1058
1059 priv->card = card;
1060 priv->hw_host_to_card = if_sdio_host_to_card;
Amitkumar Karwar49125452009-09-30 20:04:38 -07001061 priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
1062 priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
1063 priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
Pierre Ossman727c26e2007-10-17 22:24:24 +02001064
David Woodhouseaa21c002007-12-08 20:04:36 +00001065 priv->fw_ready = 1;
Pierre Ossman727c26e2007-10-17 22:24:24 +02001066
Bing Zhaob136a142009-05-19 19:48:19 -07001067 sdio_claim_host(func);
1068
1069 /*
1070 * Get rx_unit if the chip is SD8688 or newer.
1071 * SD8385 & SD8686 do not have rx_unit.
1072 */
1073 if ((card->model != IF_SDIO_MODEL_8385)
1074 && (card->model != IF_SDIO_MODEL_8686))
1075 card->rx_unit = if_sdio_read_rx_unit(card);
1076 else
1077 card->rx_unit = 0;
1078
Pierre Ossman727c26e2007-10-17 22:24:24 +02001079 /*
1080 * Enable interrupts now that everything is set up
1081 */
Pierre Ossman727c26e2007-10-17 22:24:24 +02001082 sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
1083 sdio_release_host(func);
1084 if (ret)
1085 goto reclaim;
1086
Bing Zhaod26285f82009-05-19 19:48:20 -07001087 /*
1088 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
1089 */
Bing Zhao6bc61f42009-06-01 18:04:36 -07001090 if (card->model == IF_SDIO_MODEL_8688) {
1091 struct cmd_header cmd;
1092
1093 memset(&cmd, 0, sizeof(cmd));
1094
1095 lbs_deb_sdio("send function INIT command\n");
1096 if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
1097 lbs_cmd_copyback, (unsigned long) &cmd))
1098 lbs_pr_alert("CMD_FUNC_INIT cmd failed\n");
1099 }
Bing Zhaod26285f82009-05-19 19:48:20 -07001100
Holger Schurig10078322007-11-15 18:05:47 -05001101 ret = lbs_start_card(priv);
Pierre Ossman727c26e2007-10-17 22:24:24 +02001102 if (ret)
1103 goto err_activate_card;
1104
1105out:
1106 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
1107
1108 return ret;
1109
1110err_activate_card:
Dan Williams9b02f412009-02-20 12:27:38 -05001111 flush_workqueue(card->workqueue);
1112 lbs_remove_card(priv);
Pierre Ossman727c26e2007-10-17 22:24:24 +02001113reclaim:
1114 sdio_claim_host(func);
1115release_int:
1116 sdio_release_irq(func);
1117disable:
1118 sdio_disable_func(func);
1119release:
1120 sdio_release_host(func);
1121free:
Dan Williams9b02f412009-02-20 12:27:38 -05001122 destroy_workqueue(card->workqueue);
Pierre Ossman727c26e2007-10-17 22:24:24 +02001123 while (card->packets) {
1124 packet = card->packets;
1125 card->packets = card->packets->next;
1126 kfree(packet);
1127 }
1128
1129 kfree(card);
1130
1131 goto out;
1132}
1133
1134static void if_sdio_remove(struct sdio_func *func)
1135{
1136 struct if_sdio_card *card;
1137 struct if_sdio_packet *packet;
1138
1139 lbs_deb_enter(LBS_DEB_SDIO);
1140
1141 card = sdio_get_drvdata(func);
1142
Bing Zhao6bc61f42009-06-01 18:04:36 -07001143 if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
1144 /*
1145 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
1146 * multiple functions
1147 */
1148 struct cmd_header cmd;
1149
1150 memset(&cmd, 0, sizeof(cmd));
1151
1152 lbs_deb_sdio("send function SHUTDOWN command\n");
1153 if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN,
1154 &cmd, sizeof(cmd), lbs_cmd_copyback,
1155 (unsigned long) &cmd))
1156 lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n");
1157 }
Bing Zhaod26285f82009-05-19 19:48:20 -07001158
Pierre Ossman727c26e2007-10-17 22:24:24 +02001159
1160 lbs_deb_sdio("call remove card\n");
Bing Zhao6bc61f42009-06-01 18:04:36 -07001161 lbs_stop_card(card->priv);
Holger Schurig10078322007-11-15 18:05:47 -05001162 lbs_remove_card(card->priv);
Andrey Yurovsky23b149c2009-06-17 19:15:19 -07001163 card->priv->surpriseremoved = 1;
Pierre Ossman727c26e2007-10-17 22:24:24 +02001164
Dan Williams9b02f412009-02-20 12:27:38 -05001165 flush_workqueue(card->workqueue);
1166 destroy_workqueue(card->workqueue);
Pierre Ossman727c26e2007-10-17 22:24:24 +02001167
1168 sdio_claim_host(func);
1169 sdio_release_irq(func);
1170 sdio_disable_func(func);
1171 sdio_release_host(func);
1172
1173 while (card->packets) {
1174 packet = card->packets;
1175 card->packets = card->packets->next;
1176 kfree(packet);
1177 }
1178
1179 kfree(card);
1180
1181 lbs_deb_leave(LBS_DEB_SDIO);
1182}
1183
1184static struct sdio_driver if_sdio_driver = {
1185 .name = "libertas_sdio",
1186 .id_table = if_sdio_ids,
1187 .probe = if_sdio_probe,
1188 .remove = if_sdio_remove,
1189};
1190
1191/*******************************************************************/
1192/* Module functions */
1193/*******************************************************************/
1194
Andres Salomon4fb910f2007-11-20 17:43:45 -05001195static int __init if_sdio_init_module(void)
Pierre Ossman727c26e2007-10-17 22:24:24 +02001196{
1197 int ret = 0;
1198
1199 lbs_deb_enter(LBS_DEB_SDIO);
1200
1201 printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n");
1202 printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n");
1203
1204 ret = sdio_register_driver(&if_sdio_driver);
1205
Bing Zhao6bc61f42009-06-01 18:04:36 -07001206 /* Clear the flag in case user removes the card. */
1207 user_rmmod = 0;
1208
Pierre Ossman727c26e2007-10-17 22:24:24 +02001209 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
1210
1211 return ret;
1212}
1213
Andres Salomon4fb910f2007-11-20 17:43:45 -05001214static void __exit if_sdio_exit_module(void)
Pierre Ossman727c26e2007-10-17 22:24:24 +02001215{
1216 lbs_deb_enter(LBS_DEB_SDIO);
1217
Bing Zhao6bc61f42009-06-01 18:04:36 -07001218 /* Set the flag as user is removing this module. */
1219 user_rmmod = 1;
Bing Zhaod26285f82009-05-19 19:48:20 -07001220
Pierre Ossman727c26e2007-10-17 22:24:24 +02001221 sdio_unregister_driver(&if_sdio_driver);
1222
1223 lbs_deb_leave(LBS_DEB_SDIO);
1224}
1225
1226module_init(if_sdio_init_module);
1227module_exit(if_sdio_exit_module);
1228
1229MODULE_DESCRIPTION("Libertas SDIO WLAN Driver");
1230MODULE_AUTHOR("Pierre Ossman");
1231MODULE_LICENSE("GPL");