aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/btmrvl_sdio.c
diff options
context:
space:
mode:
authorKevin Gan <ganhy@marvell.com>2011-04-08 21:19:33 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-04-13 11:20:05 -0400
commit9f72c1d977e47a7d182d49ea131067cba0a96ab8 (patch)
tree2f0f2627c3cad459994639617bd55e050fd1d17a /drivers/bluetooth/btmrvl_sdio.c
parentb86ed368f1f0b19de1918c57e4b056e73d5613a0 (diff)
Bluetooth: btmrvl: support Marvell Bluetooth device SD8787
The SD8787 firmware image is shared with mwifiex driver. Whoever gets loaded first will be responsible for firmware downloading. Signed-off-by: Kevin Gan <ganhy@marvell.com> Signed-off-by: Tristan Xu <xurf@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'drivers/bluetooth/btmrvl_sdio.c')
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c124
1 files changed, 94 insertions, 30 deletions
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index dcc2a6ec23f0..7f521d4ac657 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -49,15 +49,59 @@
49static u8 user_rmmod; 49static u8 user_rmmod;
50static u8 sdio_ireg; 50static u8 sdio_ireg;
51 51
52static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
53 .cfg = 0x03,
54 .host_int_mask = 0x04,
55 .host_intstatus = 0x05,
56 .card_status = 0x20,
57 .sq_read_base_addr_a0 = 0x10,
58 .sq_read_base_addr_a1 = 0x11,
59 .card_fw_status0 = 0x40,
60 .card_fw_status1 = 0x41,
61 .card_rx_len = 0x42,
62 .card_rx_unit = 0x43,
63 .io_port_0 = 0x00,
64 .io_port_1 = 0x01,
65 .io_port_2 = 0x02,
66};
67static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
68 .cfg = 0x00,
69 .host_int_mask = 0x02,
70 .host_intstatus = 0x03,
71 .card_status = 0x30,
72 .sq_read_base_addr_a0 = 0x40,
73 .sq_read_base_addr_a1 = 0x41,
74 .card_revision = 0x5c,
75 .card_fw_status0 = 0x60,
76 .card_fw_status1 = 0x61,
77 .card_rx_len = 0x62,
78 .card_rx_unit = 0x63,
79 .io_port_0 = 0x78,
80 .io_port_1 = 0x79,
81 .io_port_2 = 0x7a,
82};
83
52static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { 84static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
53 .helper = "sd8688_helper.bin", 85 .helper = "sd8688_helper.bin",
54 .firmware = "sd8688.bin", 86 .firmware = "sd8688.bin",
87 .reg = &btmrvl_reg_8688,
88 .sd_blksz_fw_dl = 64,
89};
90
91static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
92 .helper = NULL,
93 .firmware = "mrvl/sd8787_uapsta.bin",
94 .reg = &btmrvl_reg_8787,
95 .sd_blksz_fw_dl = 256,
55}; 96};
56 97
57static const struct sdio_device_id btmrvl_sdio_ids[] = { 98static const struct sdio_device_id btmrvl_sdio_ids[] = {
58 /* Marvell SD8688 Bluetooth device */ 99 /* Marvell SD8688 Bluetooth device */
59 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), 100 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
60 .driver_data = (unsigned long) &btmrvl_sdio_sd6888 }, 101 .driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
102 /* Marvell SD8787 Bluetooth device */
103 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
104 .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
61 105
62 { } /* Terminating entry */ 106 { } /* Terminating entry */
63}; 107};
@@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
69 u8 reg; 113 u8 reg;
70 int ret; 114 int ret;
71 115
72 reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret); 116 reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
73 if (!ret) 117 if (!ret)
74 card->rx_unit = reg; 118 card->rx_unit = reg;
75 119
@@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
83 127
84 *dat = 0; 128 *dat = 0;
85 129
86 fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); 130 fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
87 if (ret) 131 if (ret)
88 return -EIO; 132 return -EIO;
89 133
90 fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); 134 fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
91 if (ret) 135 if (ret)
92 return -EIO; 136 return -EIO;
93 137
@@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
101 u8 reg; 145 u8 reg;
102 int ret; 146 int ret;
103 147
104 reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret); 148 reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
105 if (!ret) 149 if (!ret)
106 *dat = (u16) reg << card->rx_unit; 150 *dat = (u16) reg << card->rx_unit;
107 151
@@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
113{ 157{
114 int ret; 158 int ret;
115 159
116 sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret); 160 sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
117 if (ret) { 161 if (ret) {
118 BT_ERR("Unable to enable the host interrupt!"); 162 BT_ERR("Unable to enable the host interrupt!");
119 ret = -EIO; 163 ret = -EIO;
@@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
128 u8 host_int_mask; 172 u8 host_int_mask;
129 int ret; 173 int ret;
130 174
131 host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret); 175 host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
132 if (ret) 176 if (ret)
133 return -EIO; 177 return -EIO;
134 178
135 host_int_mask &= ~mask; 179 host_int_mask &= ~mask;
136 180
137 sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret); 181 sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
138 if (ret < 0) { 182 if (ret < 0) {
139 BT_ERR("Unable to disable the host interrupt!"); 183 BT_ERR("Unable to disable the host interrupt!");
140 return -EIO; 184 return -EIO;
@@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
150 int ret; 194 int ret;
151 195
152 for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { 196 for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
153 status = sdio_readb(card->func, CARD_STATUS_REG, &ret); 197 status = sdio_readb(card->func, card->reg->card_status, &ret);
154 if (ret) 198 if (ret)
155 goto failed; 199 goto failed;
156 if ((status & bits) == bits) 200 if ((status & bits) == bits)
@@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
299 u8 base0, base1; 343 u8 base0, base1;
300 void *tmpfwbuf = NULL; 344 void *tmpfwbuf = NULL;
301 u8 *fwbuf; 345 u8 *fwbuf;
302 u16 len; 346 u16 len, blksz_dl = card->sd_blksz_fw_dl;
303 int txlen = 0, tx_blocks = 0, count = 0; 347 int txlen = 0, tx_blocks = 0, count = 0;
304 348
305 ret = request_firmware(&fw_firmware, card->firmware, 349 ret = request_firmware(&fw_firmware, card->firmware,
@@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
345 389
346 for (tries = 0; tries < MAX_POLL_TRIES; tries++) { 390 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
347 base0 = sdio_readb(card->func, 391 base0 = sdio_readb(card->func,
348 SQ_READ_BASE_ADDRESS_A0_REG, &ret); 392 card->reg->sq_read_base_addr_a0, &ret);
349 if (ret) { 393 if (ret) {
350 BT_ERR("BASE0 register read failed:" 394 BT_ERR("BASE0 register read failed:"
351 " base0 = 0x%04X(%d)." 395 " base0 = 0x%04X(%d)."
@@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
355 goto done; 399 goto done;
356 } 400 }
357 base1 = sdio_readb(card->func, 401 base1 = sdio_readb(card->func,
358 SQ_READ_BASE_ADDRESS_A1_REG, &ret); 402 card->reg->sq_read_base_addr_a1, &ret);
359 if (ret) { 403 if (ret) {
360 BT_ERR("BASE1 register read failed:" 404 BT_ERR("BASE1 register read failed:"
361 " base1 = 0x%04X(%d)." 405 " base1 = 0x%04X(%d)."
@@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
403 if (firmwarelen - offset < txlen) 447 if (firmwarelen - offset < txlen)
404 txlen = firmwarelen - offset; 448 txlen = firmwarelen - offset;
405 449
406 tx_blocks = 450 tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
407 (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
408 451
409 memcpy(fwbuf, &firmware[offset], txlen); 452 memcpy(fwbuf, &firmware[offset], txlen);
410 } 453 }
411 454
412 ret = sdio_writesb(card->func, card->ioport, fwbuf, 455 ret = sdio_writesb(card->func, card->ioport, fwbuf,
413 tx_blocks * SDIO_BLOCK_SIZE); 456 tx_blocks * blksz_dl);
414 457
415 if (ret < 0) { 458 if (ret < 0) {
416 BT_ERR("FW download, writesb(%d) failed @%d", 459 BT_ERR("FW download, writesb(%d) failed @%d",
417 count, offset); 460 count, offset);
418 sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG, 461 sdio_writeb(card->func, HOST_CMD53_FIN,
419 &ret); 462 card->reg->cfg, &ret);
420 if (ret) 463 if (ret)
421 BT_ERR("writeb failed (CFG)"); 464 BT_ERR("writeb failed (CFG)");
422 } 465 }
@@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
597 640
598 priv = card->priv; 641 priv = card->priv;
599 642
600 ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); 643 ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
601 if (ret) { 644 if (ret) {
602 BT_ERR("sdio_readb: read int status register failed"); 645 BT_ERR("sdio_readb: read int status register failed");
603 return; 646 return;
@@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
613 656
614 sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS | 657 sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
615 UP_LD_HOST_INT_STATUS), 658 UP_LD_HOST_INT_STATUS),
616 HOST_INTSTATUS_REG, &ret); 659 card->reg->host_intstatus, &ret);
617 if (ret) { 660 if (ret) {
618 BT_ERR("sdio_writeb: clear int status register failed"); 661 BT_ERR("sdio_writeb: clear int status register failed");
619 return; 662 return;
@@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
664 goto release_irq; 707 goto release_irq;
665 } 708 }
666 709
667 reg = sdio_readb(func, IO_PORT_0_REG, &ret); 710 reg = sdio_readb(func, card->reg->io_port_0, &ret);
668 if (ret < 0) { 711 if (ret < 0) {
669 ret = -EIO; 712 ret = -EIO;
670 goto release_irq; 713 goto release_irq;
@@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
672 715
673 card->ioport = reg; 716 card->ioport = reg;
674 717
675 reg = sdio_readb(func, IO_PORT_1_REG, &ret); 718 reg = sdio_readb(func, card->reg->io_port_1, &ret);
676 if (ret < 0) { 719 if (ret < 0) {
677 ret = -EIO; 720 ret = -EIO;
678 goto release_irq; 721 goto release_irq;
@@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
680 723
681 card->ioport |= (reg << 8); 724 card->ioport |= (reg << 8);
682 725
683 reg = sdio_readb(func, IO_PORT_2_REG, &ret); 726 reg = sdio_readb(func, card->reg->io_port_2, &ret);
684 if (ret < 0) { 727 if (ret < 0) {
685 ret = -EIO; 728 ret = -EIO;
686 goto release_irq; 729 goto release_irq;
@@ -815,6 +858,8 @@ exit:
815static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card) 858static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
816{ 859{
817 int ret = 0; 860 int ret = 0;
861 u8 fws0;
862 int pollnum = MAX_POLL_TRIES;
818 863
819 if (!card || !card->func) { 864 if (!card || !card->func) {
820 BT_ERR("card or function is NULL!"); 865 BT_ERR("card or function is NULL!");
@@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
827 goto done; 872 goto done;
828 } 873 }
829 874
830 ret = btmrvl_sdio_download_helper(card); 875 /* Check if other function driver is downloading the firmware */
876 fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
831 if (ret) { 877 if (ret) {
832 BT_ERR("Failed to download helper!"); 878 BT_ERR("Failed to read FW downloading status!");
833 ret = -EIO; 879 ret = -EIO;
834 goto done; 880 goto done;
835 } 881 }
882 if (fws0) {
883 BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
884
885 /* Give other function more time to download the firmware */
886 pollnum *= 10;
887 } else {
888 if (card->helper) {
889 ret = btmrvl_sdio_download_helper(card);
890 if (ret) {
891 BT_ERR("Failed to download helper!");
892 ret = -EIO;
893 goto done;
894 }
895 }
836 896
837 if (btmrvl_sdio_download_fw_w_helper(card)) { 897 if (btmrvl_sdio_download_fw_w_helper(card)) {
838 BT_ERR("Failed to download firmware!"); 898 BT_ERR("Failed to download firmware!");
839 ret = -EIO; 899 ret = -EIO;
840 goto done; 900 goto done;
901 }
841 } 902 }
842 903
843 if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) { 904 if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
844 BT_ERR("FW failed to be active in time!"); 905 BT_ERR("FW failed to be active in time!");
845 ret = -ETIMEDOUT; 906 ret = -ETIMEDOUT;
846 goto done; 907 goto done;
@@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
864 925
865 sdio_claim_host(card->func); 926 sdio_claim_host(card->func);
866 927
867 sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret); 928 sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
868 929
869 sdio_release_host(card->func); 930 sdio_release_host(card->func);
870 931
@@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
893 954
894 if (id->driver_data) { 955 if (id->driver_data) {
895 struct btmrvl_sdio_device *data = (void *) id->driver_data; 956 struct btmrvl_sdio_device *data = (void *) id->driver_data;
896 card->helper = data->helper; 957 card->helper = data->helper;
897 card->firmware = data->firmware; 958 card->firmware = data->firmware;
959 card->reg = data->reg;
960 card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
898 } 961 }
899 962
900 if (btmrvl_sdio_register_dev(card) < 0) { 963 if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
1011MODULE_LICENSE("GPL v2"); 1074MODULE_LICENSE("GPL v2");
1012MODULE_FIRMWARE("sd8688_helper.bin"); 1075MODULE_FIRMWARE("sd8688_helper.bin");
1013MODULE_FIRMWARE("sd8688.bin"); 1076MODULE_FIRMWARE("sd8688.bin");
1077MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");