aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/Kconfig13
-rw-r--r--drivers/bluetooth/Makefile1
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c1128
-rw-r--r--drivers/bluetooth/btmrvl_sdio.h113
4 files changed, 1255 insertions, 0 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index b049a79fcc02..8c89bd4abbf6 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -182,5 +182,18 @@ config BT_MRVL
182 Say Y here to compile Marvell Bluetooth driver 182 Say Y here to compile Marvell Bluetooth driver
183 into the kernel or say M to compile it as module. 183 into the kernel or say M to compile it as module.
184 184
185config BT_MRVL_SDIO
186 tristate "Marvell BT-over-SDIO driver"
187 depends on BT_MRVL && MMC
188 help
189 The driver for Marvell Bluetooth chipsets with SDIO interface.
190
191 This driver is required if you want to use Marvell Bluetooth
192 devices with SDIO interface. Currently only SD8688 chipset is
193 supported.
194
195 Say Y here to compile support for Marvell BT-over-SDIO driver
196 into the kernel or say M to compile it as module.
197
185endmenu 198endmenu
186 199
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 3eff1231812c..2dc12e7d0155 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o
17 17
18btmrvl-objs := btmrvl_main.o 18btmrvl-objs := btmrvl_main.o
19obj-$(CONFIG_BT_MRVL) += btmrvl.o 19obj-$(CONFIG_BT_MRVL) += btmrvl.o
20obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
20 21
21hci_uart-y := hci_ldisc.o 22hci_uart-y := hci_ldisc.o
22hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o 23hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
new file mode 100644
index 000000000000..8f13e7bea0ba
--- /dev/null
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -0,0 +1,1128 @@
1/**
2 * Marvell BT-over-SDIO driver: SDIO interface related functions.
3 *
4 * Copyright (C) 2009, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 **/
20
21#include <linux/firmware.h>
22
23#include <linux/mmc/sdio_ids.h>
24#include <linux/mmc/sdio_func.h>
25
26#include <net/bluetooth/bluetooth.h>
27#include <net/bluetooth/hci_core.h>
28
29#include "btmrvl_drv.h"
30#include "btmrvl_sdio.h"
31
32#define VERSION "1.0"
33
34#ifndef SDIO_DEVICE_ID_MARVELL_8688BT
35#define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105
36#endif
37
38/* The btmrvl_sdio_remove() callback function is called
39 * when user removes this module from kernel space or ejects
40 * the card from the slot. The driver handles these 2 cases
41 * differently.
42 * If the user is removing the module, a MODULE_SHUTDOWN_REQ
43 * command is sent to firmware and interrupt will be disabled.
44 * If the card is removed, there is no need to send command
45 * or disable interrupt.
46 *
47 * The variable 'user_rmmod' is used to distinguish these two
48 * scenarios. This flag is initialized as FALSE in case the card
49 * is removed, and will be set to TRUE for module removal when
50 * module_exit function is called.
51 */
52static u8 user_rmmod;
53
54static const struct sdio_device_id btmrvl_sdio_ids[] = {
55 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8688BT)},
56 {0, 0, 0, 0}
57};
58
59MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
60
61static struct btmrvl_sdio_device btmrvl_sdio_devices[] = {
62 {
63 .dev_id = SDIO_DEVICE_ID_MARVELL_8688BT,
64 .helper = "sd8688_helper.bin",
65 .firmware = "sd8688.bin",
66 },
67};
68
69static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
70{
71 u8 reg;
72 int ret;
73
74 BT_DBG("Enter");
75
76 reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret);
77 if (!ret)
78 card->rx_unit = reg;
79
80 BT_DBG("Leave");
81
82 return ret;
83}
84
85static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
86{
87 int ret;
88 u8 fws0, fws1;
89
90 BT_DBG("Enter");
91
92 *dat = 0;
93
94 fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
95
96 if (!ret)
97 fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
98
99 if (ret) {
100 BT_DBG("Leave");
101 return -EIO;
102 }
103
104 *dat = (((u16) fws1) << 8) | fws0;
105
106 BT_DBG("Leave");
107
108 return 0;
109}
110
111static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
112{
113 int ret;
114 u8 reg;
115
116 BT_DBG("Enter");
117
118 reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret);
119 if (!ret)
120 *dat = (u16) reg << card->rx_unit;
121
122 BT_DBG("Leave");
123
124 return ret;
125}
126
127static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
128 u8 mask)
129{
130 int ret;
131
132 BT_DBG("Enter");
133
134 sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret);
135 if (ret) {
136 BT_ERR("Unable to enable the host interrupt!");
137 ret = -EIO;
138 }
139
140 BT_DBG("Leave");
141
142 return ret;
143}
144
145static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
146 u8 mask)
147{
148 int ret;
149 u8 host_int_mask;
150
151 BT_DBG("Enter");
152
153 host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret);
154 if (ret) {
155 ret = -EIO;
156 goto done;
157 }
158
159 host_int_mask &= ~mask;
160
161 sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret);
162 if (ret < 0) {
163 BT_ERR("Unable to disable the host interrupt!");
164 ret = -EIO;
165 goto done;
166 }
167
168 ret = 0;
169
170done:
171 BT_DBG("Leave");
172
173 return ret;
174}
175
176static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
177{
178 unsigned int tries;
179 int ret;
180 u8 status;
181
182 BT_DBG("Enter");
183
184 for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
185 status = sdio_readb(card->func, CARD_STATUS_REG, &ret);
186 if (ret)
187 goto failed;
188 if ((status & bits) == bits)
189 goto done;
190
191 udelay(1);
192 }
193
194 ret = -ETIMEDOUT;
195
196failed:
197 BT_ERR("FAILED! ret=%d", ret);
198
199done:
200 BT_DBG("Leave");
201
202 return ret;
203}
204
205static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
206 int pollnum)
207{
208 int ret = -ETIMEDOUT;
209 u16 firmwarestat;
210 unsigned int tries;
211
212 BT_DBG("Enter");
213
214 /* Wait for firmware to become ready */
215 for (tries = 0; tries < pollnum; tries++) {
216 if (btmrvl_sdio_read_fw_status(card, &firmwarestat) < 0)
217 continue;
218
219 if (firmwarestat == FIRMWARE_READY) {
220 ret = 0;
221 break;
222 } else {
223 msleep(10);
224 }
225 }
226
227 BT_DBG("Leave");
228
229 return ret;
230}
231
232static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
233{
234 const struct firmware *fw_helper = NULL;
235 const u8 *helper = NULL;
236 int ret;
237 void *tmphlprbuf = NULL;
238 int tmphlprbufsz, hlprblknow, helperlen;
239 u8 *helperbuf;
240 u32 tx_len;
241
242 BT_DBG("Enter");
243
244 ret = request_firmware(&fw_helper, card->helper,
245 &card->func->dev);
246 if ((ret < 0) || !fw_helper) {
247 BT_ERR("request_firmware(helper) failed, error code = %d",
248 ret);
249 ret = -ENOENT;
250 goto done;
251 }
252
253 helper = fw_helper->data;
254 helperlen = fw_helper->size;
255
256 BT_DBG("Downloading helper image (%d bytes), block size %d bytes",
257 helperlen, SDIO_BLOCK_SIZE);
258
259 tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
260
261 tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
262 if (!tmphlprbuf) {
263 BT_ERR("Unable to allocate buffer for helper."
264 " Terminating download");
265 ret = -ENOMEM;
266 goto done;
267 }
268
269 memset(tmphlprbuf, 0, tmphlprbufsz);
270
271 helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
272
273 /* Perform helper data transfer */
274 tx_len = (FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE)
275 - SDIO_HEADER_LEN;
276 hlprblknow = 0;
277
278 do {
279 ret = btmrvl_sdio_poll_card_status(card,
280 CARD_IO_READY | DN_LD_CARD_RDY);
281 if (ret < 0) {
282 BT_ERR("Helper download poll status timeout @ %d",
283 hlprblknow);
284 goto done;
285 }
286
287 /* Check if there is more data? */
288 if (hlprblknow >= helperlen)
289 break;
290
291 if (helperlen - hlprblknow < tx_len)
292 tx_len = helperlen - hlprblknow;
293
294 /* Little-endian */
295 helperbuf[0] = ((tx_len & 0x000000ff) >> 0);
296 helperbuf[1] = ((tx_len & 0x0000ff00) >> 8);
297 helperbuf[2] = ((tx_len & 0x00ff0000) >> 16);
298 helperbuf[3] = ((tx_len & 0xff000000) >> 24);
299
300 memcpy(&helperbuf[SDIO_HEADER_LEN], &helper[hlprblknow],
301 tx_len);
302
303 /* Now send the data */
304 ret = sdio_writesb(card->func, card->ioport,
305 helperbuf,
306 FIRMWARE_TRANSFER_NBLOCK *
307 SDIO_BLOCK_SIZE);
308 if (ret < 0) {
309 BT_ERR("IO error during helper download @ %d",
310 hlprblknow);
311 goto done;
312 }
313
314 hlprblknow += tx_len;
315 } while (true);
316
317 BT_DBG("Transferring helper image EOF block");
318
319 memset(helperbuf, 0x0, SDIO_BLOCK_SIZE);
320
321 ret = sdio_writesb(card->func, card->ioport, helperbuf,
322 SDIO_BLOCK_SIZE);
323 if (ret < 0) {
324 BT_ERR("IO error in writing helper image EOF block");
325 goto done;
326 }
327
328 ret = 0;
329
330done:
331 kfree(tmphlprbuf);
332 if (fw_helper)
333 release_firmware(fw_helper);
334
335 BT_DBG("Leave");
336
337 return ret;
338}
339
340static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
341{
342 const struct firmware *fw_firmware = NULL;
343 const u8 *firmware = NULL;
344 int firmwarelen, tmpfwbufsz, ret;
345 unsigned int tries, offset;
346 u8 base0, base1;
347 void *tmpfwbuf = NULL;
348 u8 *fwbuf;
349 u16 len;
350 int txlen = 0, tx_blocks = 0, count = 0;
351
352 BT_DBG("Enter");
353
354 ret = request_firmware(&fw_firmware, card->firmware,
355 &card->func->dev);
356 if ((ret < 0) || !fw_firmware) {
357 BT_ERR("request_firmware(firmware) failed, error code = %d",
358 ret);
359 ret = -ENOENT;
360 goto done;
361 }
362
363 firmware = fw_firmware->data;
364 firmwarelen = fw_firmware->size;
365
366 BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
367
368 tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
369 tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
370 if (!tmpfwbuf) {
371 BT_ERR("Unable to allocate buffer for firmware."
372 " Terminating download");
373 ret = -ENOMEM;
374 goto done;
375 }
376
377 memset(tmpfwbuf, 0, tmpfwbufsz);
378
379 /* Ensure aligned firmware buffer */
380 fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
381
382 /* Perform firmware data transfer */
383 offset = 0;
384 do {
385 ret = btmrvl_sdio_poll_card_status(card,
386 CARD_IO_READY | DN_LD_CARD_RDY);
387 if (ret < 0) {
388 BT_ERR("FW download with helper poll status"
389 " timeout @ %d", offset);
390 goto done;
391 }
392
393 /* Check if there is more data ? */
394 if (offset >= firmwarelen)
395 break;
396
397 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
398 base0 = sdio_readb(card->func,
399 SQ_READ_BASE_ADDRESS_A0_REG, &ret);
400 if (ret) {
401 BT_ERR("BASE0 register read failed:"
402 " base0 = 0x%04X(%d)."
403 " Terminating download",
404 base0, base0);
405 ret = -EIO;
406 goto done;
407 }
408 base1 = sdio_readb(card->func,
409 SQ_READ_BASE_ADDRESS_A1_REG, &ret);
410 if (ret) {
411 BT_ERR("BASE1 register read failed:"
412 " base1 = 0x%04X(%d)."
413 " Terminating download",
414 base1, base1);
415 ret = -EIO;
416 goto done;
417 }
418
419 len = (((u16) base1) << 8) | base0;
420 if (len)
421 break;
422
423 udelay(10);
424 }
425
426 if (!len)
427 break;
428 else if (len > BTM_UPLD_SIZE) {
429 BT_ERR("FW download failure @%d, invalid length %d",
430 offset, len);
431 ret = -EINVAL;
432 goto done;
433 }
434
435 txlen = len;
436
437 if (len & BIT(0)) {
438 count++;
439 if (count > MAX_WRITE_IOMEM_RETRY) {
440 BT_ERR("FW download failure @%d, "
441 "over max retry count", offset);
442 ret = -EIO;
443 goto done;
444 }
445 BT_ERR("FW CRC error indicated by the helper: "
446 "len = 0x%04X, txlen = %d", len, txlen);
447 len &= ~BIT(0);
448 /* Set txlen to 0 so as to resend from same offset */
449 txlen = 0;
450 } else {
451 count = 0;
452
453 /* Last block ? */
454 if (firmwarelen - offset < txlen)
455 txlen = firmwarelen - offset;
456
457 tx_blocks =
458 (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
459
460 memcpy(fwbuf, &firmware[offset], txlen);
461 }
462
463 ret = sdio_writesb(card->func, card->ioport, fwbuf,
464 tx_blocks * SDIO_BLOCK_SIZE);
465
466 if (ret < 0) {
467 BT_ERR("FW download, writesb(%d) failed @%d",
468 count, offset);
469 sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
470 &ret);
471 if (ret)
472 BT_ERR("writeb failed (CFG)");
473 }
474
475 offset += txlen;
476 } while (true);
477
478 BT_DBG("FW download over, size %d bytes", offset);
479
480 ret = 0;
481
482done:
483 kfree(tmpfwbuf);
484
485 if (fw_firmware)
486 release_firmware(fw_firmware);
487
488 BT_DBG("Leave");
489
490 return ret;
491}
492
493static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
494{
495 u16 buf_len = 0;
496 int ret, buf_block_len, blksz;
497 struct sk_buff *skb = NULL;
498 u32 type;
499 u8 *payload = NULL;
500 struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
501 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
502
503 BT_DBG("Enter");
504
505 if (!card || !card->func) {
506 BT_ERR("card or function is NULL!");
507 ret = -EINVAL;
508 goto exit;
509 }
510
511 /* Read the length of data to be transferred */
512 ret = btmrvl_sdio_read_rx_len(card, &buf_len);
513 if (ret < 0) {
514 BT_ERR("read rx_len failed");
515 ret = -EIO;
516 goto exit;
517 }
518
519 blksz = SDIO_BLOCK_SIZE;
520 buf_block_len = (buf_len + blksz - 1) / blksz;
521
522 if (buf_len <= SDIO_HEADER_LEN
523 || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
524 BT_ERR("invalid packet length: %d", buf_len);
525 ret = -EINVAL;
526 goto exit;
527 }
528
529 /* Allocate buffer */
530 skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
531 GFP_ATOMIC);
532 if (skb == NULL) {
533 BT_ERR("No free skb");
534 goto exit;
535 }
536
537 if ((u32) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
538 skb_put(skb, (u32) skb->data & (BTSDIO_DMA_ALIGN - 1));
539 skb_pull(skb, (u32) skb->data & (BTSDIO_DMA_ALIGN - 1));
540 }
541
542 payload = skb->tail;
543
544 ret = sdio_readsb(card->func, payload, card->ioport,
545 buf_block_len * blksz);
546 if (ret < 0) {
547 BT_ERR("readsb failed: %d", ret);
548 ret = -EIO;
549 goto exit;
550 }
551
552 /* This is SDIO specific header length: byte[2][1][0], type: byte[3]
553 * (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
554 */
555
556 buf_len = payload[0];
557 buf_len |= (u16) payload[1] << 8;
558 type = payload[3];
559
560 switch (type) {
561 case HCI_ACLDATA_PKT:
562 case HCI_SCODATA_PKT:
563 case HCI_EVENT_PKT:
564 bt_cb(skb)->pkt_type = type;
565 skb->dev = (void *)hdev;
566 skb_put(skb, buf_len);
567 skb_pull(skb, SDIO_HEADER_LEN);
568
569 if (type == HCI_EVENT_PKT)
570 btmrvl_check_evtpkt(priv, skb);
571
572 hci_recv_frame(skb);
573 hdev->stat.byte_rx += buf_len;
574 break;
575
576 case MRVL_VENDOR_PKT:
577 bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
578 skb->dev = (void *)hdev;
579 skb_put(skb, buf_len);
580 skb_pull(skb, SDIO_HEADER_LEN);
581
582 if (btmrvl_process_event(priv, skb))
583 hci_recv_frame(skb);
584
585 hdev->stat.byte_rx += buf_len;
586 break;
587
588 default:
589 BT_ERR("Unknow packet type:%d", type);
590 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
591 blksz * buf_block_len);
592
593 kfree_skb(skb);
594 skb = NULL;
595 break;
596 }
597
598exit:
599 if (ret) {
600 hdev->stat.err_rx++;
601 if (skb)
602 kfree_skb(skb);
603 }
604
605 BT_DBG("Leave");
606
607 return ret;
608}
609
610static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
611{
612 int ret;
613 u8 sdio_ireg = 0;
614 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
615
616 BT_DBG("Enter");
617
618 *ireg = 0;
619
620 sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
621 if (ret) {
622 BT_ERR("sdio_readb: read int status register failed");
623 ret = -EIO;
624 goto done;
625 }
626
627 if (sdio_ireg != 0) {
628 /*
629 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
630 * Clear the interrupt status register and re-enable the
631 * interrupt.
632 */
633 BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
634
635 sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
636 UP_LD_HOST_INT_STATUS),
637 HOST_INTSTATUS_REG, &ret);
638 if (ret) {
639 BT_ERR("sdio_writeb: clear int status register "
640 "failed");
641 ret = -EIO;
642 goto done;
643 }
644 }
645
646 if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
647 if (priv->btmrvl_dev.tx_dnld_rdy)
648 BT_DBG("tx_done already received: "
649 " int_status=0x%x", sdio_ireg);
650 else
651 priv->btmrvl_dev.tx_dnld_rdy = true;
652 }
653
654 if (sdio_ireg & UP_LD_HOST_INT_STATUS)
655 btmrvl_sdio_card_to_host(priv);
656
657 *ireg = sdio_ireg;
658
659 ret = 0;
660
661done:
662 BT_DBG("Leave");
663
664 return ret;
665}
666
667static void btmrvl_sdio_interrupt(struct sdio_func *func)
668{
669 struct btmrvl_private *priv;
670 struct hci_dev *hcidev;
671 struct btmrvl_sdio_card *card;
672 u8 ireg = 0;
673
674 BT_DBG("Enter");
675
676 card = sdio_get_drvdata(func);
677 if (card && card->priv) {
678 priv = card->priv;
679 hcidev = priv->btmrvl_dev.hcidev;
680
681 if (btmrvl_sdio_get_int_status(priv, &ireg))
682 BT_ERR("reading HOST_INT_STATUS_REG failed");
683 else
684 BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
685
686 btmrvl_interrupt(priv);
687 }
688
689 BT_DBG("Leave");
690}
691
692static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
693{
694 int ret = 0, i;
695 u8 reg;
696 struct sdio_func *func;
697
698 BT_DBG("Enter");
699
700 if (!card || !card->func) {
701 BT_ERR("Error: card or function is NULL!");
702 ret = -EINVAL;
703 goto failed;
704 }
705
706 func = card->func;
707
708 for (i = 0; i < ARRAY_SIZE(btmrvl_sdio_devices); i++) {
709 if (func->device == btmrvl_sdio_devices[i].dev_id)
710 break;
711 }
712
713 if (i == ARRAY_SIZE(btmrvl_sdio_devices)) {
714 BT_ERR("Error: unknown device id 0x%x", func->device);
715 ret = -EINVAL;
716 goto failed;
717 }
718
719 card->helper = btmrvl_sdio_devices[i].helper;
720 card->firmware = btmrvl_sdio_devices[i].firmware;
721
722 sdio_claim_host(func);
723
724 ret = sdio_enable_func(func);
725 if (ret) {
726 BT_ERR("sdio_enable_func() failed: ret=%d", ret);
727 ret = -EIO;
728 goto release_host;
729 }
730
731 ret = sdio_claim_irq(func, btmrvl_sdio_interrupt);
732 if (ret) {
733 BT_ERR("sdio_claim_irq failed: ret=%d", ret);
734 ret = -EIO;
735 goto disable_func;
736 }
737
738 ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE);
739 if (ret) {
740 BT_ERR("cannot set SDIO block size");
741 ret = -EIO;
742 goto release_irq;
743 }
744
745 reg = sdio_readb(func, IO_PORT_0_REG, &ret);
746 if (ret < 0) {
747 ret = -EIO;
748 goto release_irq;
749 }
750
751 card->ioport = reg;
752
753 reg = sdio_readb(func, IO_PORT_1_REG, &ret);
754 if (ret < 0) {
755 ret = -EIO;
756 goto release_irq;
757 }
758
759 card->ioport |= (reg << 8);
760
761 reg = sdio_readb(func, IO_PORT_2_REG, &ret);
762 if (ret < 0) {
763 ret = -EIO;
764 goto release_irq;
765 }
766
767 card->ioport |= (reg << 16);
768
769 BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
770
771 sdio_set_drvdata(func, card);
772
773 sdio_release_host(func);
774
775 BT_DBG("Leave");
776 return 0;
777
778release_irq:
779 sdio_release_irq(func);
780
781disable_func:
782 sdio_disable_func(func);
783
784release_host:
785 sdio_release_host(func);
786
787failed:
788 BT_DBG("Leave");
789 return ret;
790}
791
792static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
793{
794 BT_DBG("Enter");
795
796 if (card && card->func) {
797 sdio_claim_host(card->func);
798 sdio_release_irq(card->func);
799 sdio_disable_func(card->func);
800 sdio_release_host(card->func);
801 sdio_set_drvdata(card->func, NULL);
802 }
803
804 BT_DBG("Leave");
805
806 return 0;
807}
808
809static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
810{
811 int ret;
812
813 BT_DBG("Enter");
814
815 if (!card || !card->func) {
816 BT_DBG("Leave");
817 return -EINVAL;
818 }
819
820 sdio_claim_host(card->func);
821
822 ret = btmrvl_sdio_enable_host_int_mask(card, HIM_ENABLE);
823
824 btmrvl_sdio_get_rx_unit(card);
825
826 sdio_release_host(card->func);
827
828 BT_DBG("Leave");
829
830 return ret;
831}
832
833static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
834{
835 int ret;
836
837 BT_DBG("Enter");
838
839 if (!card || !card->func) {
840 BT_DBG("Leave");
841 return -EINVAL;
842 }
843
844 sdio_claim_host(card->func);
845
846 ret = btmrvl_sdio_disable_host_int_mask(card, HIM_DISABLE);
847
848 sdio_release_host(card->func);
849
850 BT_DBG("Leave");
851
852 return ret;
853}
854
855static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
856 u8 *payload, u16 nb)
857{
858 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
859 int ret = 0;
860 int buf_block_len;
861 int blksz;
862 int i = 0;
863 u8 *buf = NULL;
864 void *tmpbuf = NULL;
865 int tmpbufsz;
866
867 BT_DBG("Enter");
868
869 if (!card || !card->func) {
870 BT_ERR("card or function is NULL!");
871 BT_DBG("Leave");
872 return -EINVAL;
873 }
874
875 buf = payload;
876 if ((u32) payload & (BTSDIO_DMA_ALIGN - 1)) {
877 tmpbufsz = ALIGN_SZ(nb, BTSDIO_DMA_ALIGN);
878 tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
879 memset(tmpbuf, 0, tmpbufsz);
880 buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN);
881 memcpy(buf, payload, nb);
882 }
883
884 blksz = SDIO_BLOCK_SIZE;
885 buf_block_len = (nb + blksz - 1) / blksz;
886
887 sdio_claim_host(card->func);
888
889 do {
890 /* Transfer data to card */
891 ret = sdio_writesb(card->func, card->ioport, buf,
892 buf_block_len * blksz);
893 if (ret < 0) {
894 i++;
895 BT_ERR("i=%d writesb failed: %d", i, ret);
896 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
897 payload, nb);
898 ret = -EIO;
899 if (i > MAX_WRITE_IOMEM_RETRY)
900 goto exit;
901 }
902 } while (ret);
903
904 priv->btmrvl_dev.tx_dnld_rdy = false;
905
906exit:
907 sdio_release_host(card->func);
908
909 BT_DBG("Leave");
910
911 return ret;
912}
913
914static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
915{
916 int ret = 0;
917
918 BT_DBG("Enter");
919
920 if (!card || !card->func) {
921 BT_ERR("card or function is NULL!");
922 BT_DBG("Leave");
923 return -EINVAL;
924 }
925 sdio_claim_host(card->func);
926
927 if (!btmrvl_sdio_verify_fw_download(card, 1)) {
928 BT_DBG("Firmware already downloaded!");
929 goto done;
930 }
931
932 ret = btmrvl_sdio_download_helper(card);
933 if (ret) {
934 BT_ERR("Failed to download helper!");
935 ret = -EIO;
936 goto done;
937 }
938
939 if (btmrvl_sdio_download_fw_w_helper(card)) {
940 BT_ERR("Failed to download firmware!");
941 ret = -EIO;
942 goto done;
943 }
944
945 if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) {
946 BT_ERR("FW failed to be active in time!");
947 ret = -ETIMEDOUT;
948 goto done;
949 }
950
951done:
952 sdio_release_host(card->func);
953
954 BT_DBG("Leave");
955
956 return ret;
957}
958
959static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
960{
961 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
962 int ret = 0;
963
964 BT_DBG("Enter");
965
966 if (!card || !card->func) {
967 BT_ERR("card or function is NULL!");
968 BT_DBG("Leave");
969 return -EINVAL;
970 }
971
972 sdio_claim_host(card->func);
973
974 sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret);
975
976 sdio_release_host(card->func);
977
978 BT_DBG("wake up firmware");
979
980 BT_DBG("Leave");
981
982 return ret;
983}
984
985static int btmrvl_sdio_probe(struct sdio_func *func,
986 const struct sdio_device_id *id)
987{
988 int ret = 0;
989 struct btmrvl_private *priv = NULL;
990 struct btmrvl_sdio_card *card = NULL;
991
992 BT_DBG("Enter");
993
994 BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
995 id->vendor, id->device, id->class, func->num);
996
997 card = kzalloc(sizeof(*card), GFP_KERNEL);
998 if (!card) {
999 ret = -ENOMEM;
1000 goto done;
1001 }
1002
1003 card->func = func;
1004
1005 if (btmrvl_sdio_register_dev(card) < 0) {
1006 BT_ERR("Failed to register BT device!");
1007 ret = -ENODEV;
1008 goto free_card;
1009 }
1010
1011 /* Disable the interrupts on the card */
1012 btmrvl_sdio_disable_host_int(card);
1013
1014 if (btmrvl_sdio_download_fw(card)) {
1015 BT_ERR("Downloading firmware failed!");
1016 ret = -ENODEV;
1017 goto unreg_dev;
1018 }
1019
1020 msleep(100);
1021
1022 btmrvl_sdio_enable_host_int(card);
1023
1024 priv = btmrvl_add_card(card);
1025 if (!priv) {
1026 BT_ERR("Initializing card failed!");
1027 ret = -ENODEV;
1028 goto disable_host_int;
1029 }
1030
1031 card->priv = priv;
1032
1033 /* Initialize the interface specific function pointers */
1034 priv->hw_host_to_card = btmrvl_sdio_host_to_card;
1035 priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
1036
1037 strncpy(priv->btmrvl_dev.name, "btmrvl_sdio0",
1038 sizeof(priv->btmrvl_dev.name));
1039
1040 btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
1041
1042 BT_DBG("Leave");
1043
1044 return 0;
1045
1046disable_host_int:
1047 btmrvl_sdio_disable_host_int(card);
1048unreg_dev:
1049 btmrvl_sdio_unregister_dev(card);
1050free_card:
1051 kfree(card);
1052done:
1053 BT_DBG("Leave");
1054
1055 return ret;
1056}
1057
1058static void btmrvl_sdio_remove(struct sdio_func *func)
1059{
1060 struct btmrvl_sdio_card *card;
1061
1062 BT_DBG("Enter");
1063
1064 if (func) {
1065 card = sdio_get_drvdata(func);
1066 if (card) {
1067 /* Send SHUTDOWN command & disable interrupt
1068 * if user removes the module.
1069 */
1070 if (user_rmmod) {
1071 btmrvl_send_module_cfg_cmd(card->priv,
1072 MODULE_SHUTDOWN_REQ);
1073 btmrvl_sdio_disable_host_int(card);
1074 }
1075 BT_DBG("unregester dev");
1076 btmrvl_sdio_unregister_dev(card);
1077 btmrvl_remove_card(card->priv);
1078 kfree(card);
1079 }
1080 }
1081
1082 BT_DBG("Leave");
1083}
1084
1085static struct sdio_driver bt_mrvl_sdio = {
1086 .name = "btmrvl_sdio",
1087 .id_table = btmrvl_sdio_ids,
1088 .probe = btmrvl_sdio_probe,
1089 .remove = btmrvl_sdio_remove,
1090};
1091
1092static int btmrvl_sdio_init_module(void)
1093{
1094 BT_DBG("Enter");
1095
1096 if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
1097 BT_ERR("SDIO Driver Registration Failed");
1098 BT_DBG("Leave");
1099 return -ENODEV;
1100 }
1101
1102 /* Clear the flag in case user removes the card. */
1103 user_rmmod = 0;
1104
1105 BT_DBG("Leave");
1106
1107 return 0;
1108}
1109
1110static void btmrvl_sdio_exit_module(void)
1111{
1112 BT_DBG("Enter");
1113
1114 /* Set the flag as user is removing this module. */
1115 user_rmmod = 1;
1116
1117 sdio_unregister_driver(&bt_mrvl_sdio);
1118
1119 BT_DBG("Leave");
1120}
1121
1122module_init(btmrvl_sdio_init_module);
1123module_exit(btmrvl_sdio_exit_module);
1124
1125MODULE_AUTHOR("Marvell International Ltd.");
1126MODULE_DESCRIPTION("Marvell BT-over-SDIO Driver v" VERSION);
1127MODULE_VERSION(VERSION);
1128MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
new file mode 100644
index 000000000000..08bef333ded9
--- /dev/null
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -0,0 +1,113 @@
1/**
2 * Marvell BT-over-SDIO driver: SDIO interface related definitions
3 *
4 * Copyright (C) 2009, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 *
20 **/
21
22#ifndef _BTMRVL_SDIO_H_
23#define _BTMRVL_SDIO_H_
24
25#define SDIO_HEADER_LEN 4
26
27/* SD block size can not bigger than 64 due to buf size limit in firmware */
28/* define SD block size for data Tx/Rx */
29#define SDIO_BLOCK_SIZE 64
30
31/* Number of blocks for firmware transfer */
32#define FIRMWARE_TRANSFER_NBLOCK 2
33
34/* This is for firmware specific length */
35#define FW_EXTRA_LEN 36
36
37#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
38
39#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
40 (HCI_MAX_FRAME_SIZE + FW_EXTRA_LEN)
41
42#define ALLOC_BUF_SIZE (((max_t (int, MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
43 MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
44 + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE) \
45 * SDIO_BLOCK_SIZE)
46
47/* The number of times to try when polling for status */
48#define MAX_POLL_TRIES 100
49
50/* Max retry number of CMD53 write */
51#define MAX_WRITE_IOMEM_RETRY 2
52
53/* Host Control Registers */
54#define IO_PORT_0_REG 0x00
55#define IO_PORT_1_REG 0x01
56#define IO_PORT_2_REG 0x02
57
58#define CONFIG_REG 0x03
59#define HOST_POWER_UP BIT(1)
60#define HOST_CMD53_FIN BIT(2)
61
62#define HOST_INT_MASK_REG 0x04
63#define HIM_DISABLE 0xff
64#define HIM_ENABLE (BIT(0) | BIT(1))
65
66#define HOST_INTSTATUS_REG 0x05
67#define UP_LD_HOST_INT_STATUS BIT(0)
68#define DN_LD_HOST_INT_STATUS BIT(1)
69
70/* Card Control Registers */
71#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
72#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
73
74#define CARD_STATUS_REG 0x20
75#define DN_LD_CARD_RDY BIT(0)
76#define CARD_IO_READY BIT(3)
77
78#define CARD_FW_STATUS0_REG 0x40
79#define CARD_FW_STATUS1_REG 0x41
80#define FIRMWARE_READY 0xfedc
81
82#define CARD_RX_LEN_REG 0x42
83#define CARD_RX_UNIT_REG 0x43
84
85
86struct btmrvl_sdio_card {
87 struct sdio_func *func;
88 u32 ioport;
89 const char *helper;
90 const char *firmware;
91 u8 rx_unit;
92 struct btmrvl_private *priv;
93};
94
95struct btmrvl_sdio_device {
96 unsigned short dev_id;
97 const char *helper;
98 const char *firmware;
99};
100
101
102/* Platform specific DMA alignment */
103#define BTSDIO_DMA_ALIGN 8
104
105/* Macros for Data Alignment : size */
106#define ALIGN_SZ(p, a) \
107 (((p) + ((a) - 1)) & ~((a) - 1))
108
109/* Macros for Data Alignment : address */
110#define ALIGN_ADDR(p, a) \
111 ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
112
113#endif /* _BTMRVL_SDIO_H_ */