Commit 9f72c1d977e47a7d182d49ea131067cba0a96ab8

Authored by Kevin Gan
Committed by Gustavo F. Padovan
1 parent b86ed368f1

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>

Showing 3 changed files with 132 additions and 64 deletions Side-by-side Diff

drivers/bluetooth/Kconfig
... ... @@ -188,7 +188,7 @@
188 188 The core driver to support Marvell Bluetooth devices.
189 189  
190 190 This driver is required if you want to support
191   - Marvell Bluetooth devices, such as 8688.
  191 + Marvell Bluetooth devices, such as 8688/8787.
192 192  
193 193 Say Y here to compile Marvell Bluetooth driver
194 194 into the kernel or say M to compile it as module.
... ... @@ -201,7 +201,7 @@
201 201 The driver for Marvell Bluetooth chipsets with SDIO interface.
202 202  
203 203 This driver is required if you want to use Marvell Bluetooth
204   - devices with SDIO interface. Currently only SD8688 chipset is
  204 + devices with SDIO interface. Currently SD8688/SD8787 chipsets are
205 205 supported.
206 206  
207 207 Say Y here to compile support for Marvell BT-over-SDIO driver
drivers/bluetooth/btmrvl_sdio.c
... ... @@ -49,15 +49,59 @@
49 49 static u8 user_rmmod;
50 50 static u8 sdio_ireg;
51 51  
  52 +static 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 +};
  67 +static 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 +
52 84 static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
53 85 .helper = "sd8688_helper.bin",
54 86 .firmware = "sd8688.bin",
  87 + .reg = &btmrvl_reg_8688,
  88 + .sd_blksz_fw_dl = 64,
55 89 };
56 90  
  91 +static 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,
  96 +};
  97 +
57 98 static const struct sdio_device_id btmrvl_sdio_ids[] = {
58 99 /* Marvell SD8688 Bluetooth device */
59 100 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
60 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 106 { } /* Terminating entry */
63 107 };
... ... @@ -69,7 +113,7 @@
69 113 u8 reg;
70 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 117 if (!ret)
74 118 card->rx_unit = reg;
75 119  
76 120  
... ... @@ -83,11 +127,11 @@
83 127  
84 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 131 if (ret)
88 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 135 if (ret)
92 136 return -EIO;
93 137  
... ... @@ -101,7 +145,7 @@
101 145 u8 reg;
102 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 149 if (!ret)
106 150 *dat = (u16) reg << card->rx_unit;
107 151  
... ... @@ -113,7 +157,7 @@
113 157 {
114 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 161 if (ret) {
118 162 BT_ERR("Unable to enable the host interrupt!");
119 163 ret = -EIO;
120 164  
... ... @@ -128,13 +172,13 @@
128 172 u8 host_int_mask;
129 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 176 if (ret)
133 177 return -EIO;
134 178  
135 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 182 if (ret < 0) {
139 183 BT_ERR("Unable to disable the host interrupt!");
140 184 return -EIO;
... ... @@ -150,7 +194,7 @@
150 194 int ret;
151 195  
152 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 198 if (ret)
155 199 goto failed;
156 200 if ((status & bits) == bits)
... ... @@ -299,7 +343,7 @@
299 343 u8 base0, base1;
300 344 void *tmpfwbuf = NULL;
301 345 u8 *fwbuf;
302   - u16 len;
  346 + u16 len, blksz_dl = card->sd_blksz_fw_dl;
303 347 int txlen = 0, tx_blocks = 0, count = 0;
304 348  
305 349 ret = request_firmware(&fw_firmware, card->firmware,
... ... @@ -345,7 +389,7 @@
345 389  
346 390 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
347 391 base0 = sdio_readb(card->func,
348   - SQ_READ_BASE_ADDRESS_A0_REG, &ret);
  392 + card->reg->sq_read_base_addr_a0, &ret);
349 393 if (ret) {
350 394 BT_ERR("BASE0 register read failed:"
351 395 " base0 = 0x%04X(%d)."
... ... @@ -355,7 +399,7 @@
355 399 goto done;
356 400 }
357 401 base1 = sdio_readb(card->func,
358   - SQ_READ_BASE_ADDRESS_A1_REG, &ret);
  402 + card->reg->sq_read_base_addr_a1, &ret);
359 403 if (ret) {
360 404 BT_ERR("BASE1 register read failed:"
361 405 " base1 = 0x%04X(%d)."
362 406  
363 407  
... ... @@ -403,20 +447,19 @@
403 447 if (firmwarelen - offset < txlen)
404 448 txlen = firmwarelen - offset;
405 449  
406   - tx_blocks =
407   - (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
  450 + tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
408 451  
409 452 memcpy(fwbuf, &firmware[offset], txlen);
410 453 }
411 454  
412 455 ret = sdio_writesb(card->func, card->ioport, fwbuf,
413   - tx_blocks * SDIO_BLOCK_SIZE);
  456 + tx_blocks * blksz_dl);
414 457  
415 458 if (ret < 0) {
416 459 BT_ERR("FW download, writesb(%d) failed @%d",
417 460 count, offset);
418   - sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
419   - &ret);
  461 + sdio_writeb(card->func, HOST_CMD53_FIN,
  462 + card->reg->cfg, &ret);
420 463 if (ret)
421 464 BT_ERR("writeb failed (CFG)");
422 465 }
... ... @@ -597,7 +640,7 @@
597 640  
598 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 644 if (ret) {
602 645 BT_ERR("sdio_readb: read int status register failed");
603 646 return;
... ... @@ -613,7 +656,7 @@
613 656  
614 657 sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
615 658 UP_LD_HOST_INT_STATUS),
616   - HOST_INTSTATUS_REG, &ret);
  659 + card->reg->host_intstatus, &ret);
617 660 if (ret) {
618 661 BT_ERR("sdio_writeb: clear int status register failed");
619 662 return;
... ... @@ -664,7 +707,7 @@
664 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 711 if (ret < 0) {
669 712 ret = -EIO;
670 713 goto release_irq;
... ... @@ -672,7 +715,7 @@
672 715  
673 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 719 if (ret < 0) {
677 720 ret = -EIO;
678 721 goto release_irq;
... ... @@ -680,7 +723,7 @@
680 723  
681 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 727 if (ret < 0) {
685 728 ret = -EIO;
686 729 goto release_irq;
... ... @@ -815,6 +858,8 @@
815 858 static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
816 859 {
817 860 int ret = 0;
  861 + u8 fws0;
  862 + int pollnum = MAX_POLL_TRIES;
818 863  
819 864 if (!card || !card->func) {
820 865 BT_ERR("card or function is NULL!");
821 866  
822 867  
823 868  
824 869  
... ... @@ -827,20 +872,36 @@
827 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 877 if (ret) {
832   - BT_ERR("Failed to download helper!");
  878 + BT_ERR("Failed to read FW downloading status!");
833 879 ret = -EIO;
834 880 goto done;
835 881 }
  882 + if (fws0) {
  883 + BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
836 884  
837   - if (btmrvl_sdio_download_fw_w_helper(card)) {
838   - BT_ERR("Failed to download firmware!");
839   - ret = -EIO;
840   - goto done;
  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 + }
  896 +
  897 + if (btmrvl_sdio_download_fw_w_helper(card)) {
  898 + BT_ERR("Failed to download firmware!");
  899 + ret = -EIO;
  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 905 BT_ERR("FW failed to be active in time!");
845 906 ret = -ETIMEDOUT;
846 907 goto done;
... ... @@ -864,7 +925,7 @@
864 925  
865 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 930 sdio_release_host(card->func);
870 931  
871 932  
... ... @@ -893,8 +954,10 @@
893 954  
894 955 if (id->driver_data) {
895 956 struct btmrvl_sdio_device *data = (void *) id->driver_data;
896   - card->helper = data->helper;
  957 + card->helper = data->helper;
897 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 963 if (btmrvl_sdio_register_dev(card) < 0) {
... ... @@ -1011,4 +1074,5 @@
1011 1074 MODULE_LICENSE("GPL v2");
1012 1075 MODULE_FIRMWARE("sd8688_helper.bin");
1013 1076 MODULE_FIRMWARE("sd8688.bin");
  1077 +MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
drivers/bluetooth/btmrvl_sdio.h
... ... @@ -47,44 +47,46 @@
47 47 /* Max retry number of CMD53 write */
48 48 #define MAX_WRITE_IOMEM_RETRY 2
49 49  
50   -/* Host Control Registers */
51   -#define IO_PORT_0_REG 0x00
52   -#define IO_PORT_1_REG 0x01
53   -#define IO_PORT_2_REG 0x02
  50 +/* register bitmasks */
  51 +#define HOST_POWER_UP BIT(1)
  52 +#define HOST_CMD53_FIN BIT(2)
54 53  
55   -#define CONFIG_REG 0x03
56   -#define HOST_POWER_UP BIT(1)
57   -#define HOST_CMD53_FIN BIT(2)
  54 +#define HIM_DISABLE 0xff
  55 +#define HIM_ENABLE (BIT(0) | BIT(1))
58 56  
59   -#define HOST_INT_MASK_REG 0x04
60   -#define HIM_DISABLE 0xff
61   -#define HIM_ENABLE (BIT(0) | BIT(1))
  57 +#define UP_LD_HOST_INT_STATUS BIT(0)
  58 +#define DN_LD_HOST_INT_STATUS BIT(1)
62 59  
63   -#define HOST_INTSTATUS_REG 0x05
64   -#define UP_LD_HOST_INT_STATUS BIT(0)
65   -#define DN_LD_HOST_INT_STATUS BIT(1)
  60 +#define DN_LD_CARD_RDY BIT(0)
  61 +#define CARD_IO_READY BIT(3)
66 62  
67   -/* Card Control Registers */
68   -#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
69   -#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
  63 +#define FIRMWARE_READY 0xfedc
70 64  
71   -#define CARD_STATUS_REG 0x20
72   -#define DN_LD_CARD_RDY BIT(0)
73   -#define CARD_IO_READY BIT(3)
74 65  
75   -#define CARD_FW_STATUS0_REG 0x40
76   -#define CARD_FW_STATUS1_REG 0x41
77   -#define FIRMWARE_READY 0xfedc
  66 +struct btmrvl_sdio_card_reg {
  67 + u8 cfg;
  68 + u8 host_int_mask;
  69 + u8 host_intstatus;
  70 + u8 card_status;
  71 + u8 sq_read_base_addr_a0;
  72 + u8 sq_read_base_addr_a1;
  73 + u8 card_revision;
  74 + u8 card_fw_status0;
  75 + u8 card_fw_status1;
  76 + u8 card_rx_len;
  77 + u8 card_rx_unit;
  78 + u8 io_port_0;
  79 + u8 io_port_1;
  80 + u8 io_port_2;
  81 +};
78 82  
79   -#define CARD_RX_LEN_REG 0x42
80   -#define CARD_RX_UNIT_REG 0x43
81   -
82   -
83 83 struct btmrvl_sdio_card {
84 84 struct sdio_func *func;
85 85 u32 ioport;
86 86 const char *helper;
87 87 const char *firmware;
  88 + const struct btmrvl_sdio_card_reg *reg;
  89 + u16 sd_blksz_fw_dl;
88 90 u8 rx_unit;
89 91 struct btmrvl_private *priv;
90 92 };
... ... @@ -92,6 +94,8 @@
92 94 struct btmrvl_sdio_device {
93 95 const char *helper;
94 96 const char *firmware;
  97 + const struct btmrvl_sdio_card_reg *reg;
  98 + u16 sd_blksz_fw_dl;
95 99 };
96 100  
97 101