blob: 796f7194a772984863c4f49335f8523651fc1a5d [file] [log] [blame]
Bing Zhao789221e2009-06-02 14:29:36 -07001/**
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
Bing Zhao433a9382013-11-01 15:28:24 -070021#include <linux/firmware.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Bing Zhao789221e2009-06-02 14:29:36 -070023
24#include <linux/mmc/sdio_ids.h>
25#include <linux/mmc/sdio_func.h>
Paul Gortmakera59b9682011-08-29 16:44:23 -040026#include <linux/module.h>
Xinming Hudc759612014-11-24 02:40:53 -080027#include <linux/devcoredump.h>
Bing Zhao789221e2009-06-02 14:29:36 -070028
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
31
32#include "btmrvl_drv.h"
33#include "btmrvl_sdio.h"
34
35#define VERSION "1.0"
36
Xinming Hudc759612014-11-24 02:40:53 -080037static struct memory_type_mapping mem_type_mapping_tbl[] = {
38 {"ITCM", NULL, 0, 0xF0},
39 {"DTCM", NULL, 0, 0xF1},
40 {"SQRAM", NULL, 0, 0xF2},
41 {"APU", NULL, 0, 0xF3},
42 {"CIU", NULL, 0, 0xF4},
43 {"ICU", NULL, 0, 0xF5},
44 {"MAC", NULL, 0, 0xF6},
45 {"EXT7", NULL, 0, 0xF7},
46 {"EXT8", NULL, 0, 0xF8},
47 {"EXT9", NULL, 0, 0xF9},
48 {"EXT10", NULL, 0, 0xFA},
49 {"EXT11", NULL, 0, 0xFB},
50 {"EXT12", NULL, 0, 0xFC},
51 {"EXT13", NULL, 0, 0xFD},
52 {"EXTLAST", NULL, 0, 0xFE},
53};
54
Xinming Hubb7f4f02016-04-26 06:57:27 -070055static const struct of_device_id btmrvl_sdio_of_match_table[] = {
56 { .compatible = "marvell,sd8897-bt" },
57 { .compatible = "marvell,sd8997-bt" },
58 { }
59};
60
61static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
62{
63 struct btmrvl_plt_wake_cfg *cfg = priv;
64
65 if (cfg->irq_bt >= 0) {
66 pr_info("%s: wake by bt", __func__);
67 cfg->wake_by_bt = true;
68 disable_irq_nosync(irq);
69 }
70
71 return IRQ_HANDLED;
72}
73
74/* This function parses device tree node using mmc subnode devicetree API.
75 * The device node is saved in card->plt_of_node.
76 * If the device tree node exists and includes interrupts attributes, this
77 * function will request platform specific wakeup interrupt.
78 */
79static int btmrvl_sdio_probe_of(struct device *dev,
80 struct btmrvl_sdio_card *card)
81{
82 struct btmrvl_plt_wake_cfg *cfg;
83 int ret;
84
85 if (!dev->of_node ||
86 !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
87 pr_err("sdio platform data not available");
88 return -1;
89 }
90
91 card->plt_of_node = dev->of_node;
92
93 card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
94 GFP_KERNEL);
95 cfg = card->plt_wake_cfg;
96 if (cfg && card->plt_of_node) {
97 cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
98 if (!cfg->irq_bt) {
99 dev_err(dev, "fail to parse irq_bt from device tree");
Jeffy Chenfd1a88d2017-01-23 12:18:52 +0800100 cfg->irq_bt = -1;
Xinming Hubb7f4f02016-04-26 06:57:27 -0700101 } else {
102 ret = devm_request_irq(dev, cfg->irq_bt,
103 btmrvl_wake_irq_bt,
104 IRQF_TRIGGER_LOW,
105 "bt_wake", cfg);
106 if (ret) {
107 dev_err(dev,
108 "Failed to request irq_bt %d (%d)\n",
109 cfg->irq_bt, ret);
110 }
111 disable_irq(cfg->irq_bt);
112 }
113 }
114
115 return 0;
116}
117
Bing Zhao789221e2009-06-02 14:29:36 -0700118/* The btmrvl_sdio_remove() callback function is called
119 * when user removes this module from kernel space or ejects
120 * the card from the slot. The driver handles these 2 cases
121 * differently.
122 * If the user is removing the module, a MODULE_SHUTDOWN_REQ
123 * command is sent to firmware and interrupt will be disabled.
124 * If the card is removed, there is no need to send command
125 * or disable interrupt.
126 *
127 * The variable 'user_rmmod' is used to distinguish these two
128 * scenarios. This flag is initialized as FALSE in case the card
129 * is removed, and will be set to TRUE for module removal when
130 * module_exit function is called.
131 */
132static u8 user_rmmod;
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700133static u8 sdio_ireg;
Bing Zhao789221e2009-06-02 14:29:36 -0700134
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700135static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
136 .cfg = 0x03,
137 .host_int_mask = 0x04,
138 .host_intstatus = 0x05,
139 .card_status = 0x20,
140 .sq_read_base_addr_a0 = 0x10,
141 .sq_read_base_addr_a1 = 0x11,
142 .card_fw_status0 = 0x40,
143 .card_fw_status1 = 0x41,
144 .card_rx_len = 0x42,
145 .card_rx_unit = 0x43,
146 .io_port_0 = 0x00,
147 .io_port_1 = 0x01,
148 .io_port_2 = 0x02,
Bing Zhao0d367402014-03-28 14:54:39 -0700149 .int_read_to_clear = false,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700150};
Bing Zhao2ac654f2011-11-16 20:40:42 -0800151static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700152 .cfg = 0x00,
153 .host_int_mask = 0x02,
154 .host_intstatus = 0x03,
155 .card_status = 0x30,
156 .sq_read_base_addr_a0 = 0x40,
157 .sq_read_base_addr_a1 = 0x41,
158 .card_revision = 0x5c,
159 .card_fw_status0 = 0x60,
160 .card_fw_status1 = 0x61,
161 .card_rx_len = 0x62,
162 .card_rx_unit = 0x63,
163 .io_port_0 = 0x78,
164 .io_port_1 = 0x79,
165 .io_port_2 = 0x7a,
Bing Zhao0d367402014-03-28 14:54:39 -0700166 .int_read_to_clear = false,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700167};
168
Xinming Hu3907d552014-09-30 06:45:33 -0400169static const struct btmrvl_sdio_card_reg btmrvl_reg_8887 = {
170 .cfg = 0x00,
171 .host_int_mask = 0x08,
172 .host_intstatus = 0x0C,
173 .card_status = 0x5C,
174 .sq_read_base_addr_a0 = 0x6C,
175 .sq_read_base_addr_a1 = 0x6D,
176 .card_revision = 0xC8,
177 .card_fw_status0 = 0x88,
178 .card_fw_status1 = 0x89,
179 .card_rx_len = 0x8A,
180 .card_rx_unit = 0x8B,
181 .io_port_0 = 0xE4,
182 .io_port_1 = 0xE5,
183 .io_port_2 = 0xE6,
184 .int_read_to_clear = true,
185 .host_int_rsr = 0x04,
186 .card_misc_cfg = 0xD8,
187};
188
Amitkumar Karwar1e3e4922014-09-30 06:45:32 -0400189static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
Bing Zhao22f2efe2013-05-13 18:15:32 -0700190 .cfg = 0x00,
191 .host_int_mask = 0x02,
192 .host_intstatus = 0x03,
193 .card_status = 0x50,
194 .sq_read_base_addr_a0 = 0x60,
195 .sq_read_base_addr_a1 = 0x61,
196 .card_revision = 0xbc,
197 .card_fw_status0 = 0xc0,
198 .card_fw_status1 = 0xc1,
199 .card_rx_len = 0xc2,
200 .card_rx_unit = 0xc3,
201 .io_port_0 = 0xd8,
202 .io_port_1 = 0xd9,
203 .io_port_2 = 0xda,
Bing Zhao0d367402014-03-28 14:54:39 -0700204 .int_read_to_clear = true,
205 .host_int_rsr = 0x01,
206 .card_misc_cfg = 0xcc,
Xinming Hudc759612014-11-24 02:40:53 -0800207 .fw_dump_ctrl = 0xe2,
208 .fw_dump_start = 0xe3,
209 .fw_dump_end = 0xea,
Bing Zhao22f2efe2013-05-13 18:15:32 -0700210};
211
Amitkumar Karwarf0ef6742015-09-21 03:06:42 -0700212static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
213 .cfg = 0x00,
214 .host_int_mask = 0x08,
215 .host_intstatus = 0x0c,
216 .card_status = 0x5c,
217 .sq_read_base_addr_a0 = 0xf8,
218 .sq_read_base_addr_a1 = 0xf9,
219 .card_revision = 0xc8,
220 .card_fw_status0 = 0xe8,
221 .card_fw_status1 = 0xe9,
222 .card_rx_len = 0xea,
223 .card_rx_unit = 0xeb,
224 .io_port_0 = 0xe4,
225 .io_port_1 = 0xe5,
226 .io_port_2 = 0xe6,
227 .int_read_to_clear = true,
228 .host_int_rsr = 0x04,
229 .card_misc_cfg = 0xD8,
230 .fw_dump_ctrl = 0xf0,
231 .fw_dump_start = 0xf1,
232 .fw_dump_end = 0xf8,
233};
234
Paul Bollec6757862011-10-05 14:56:46 +0200235static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
Lubomir Rintel77189df2013-03-13 12:04:30 +0100236 .helper = "mrvl/sd8688_helper.bin",
237 .firmware = "mrvl/sd8688.bin",
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700238 .reg = &btmrvl_reg_8688,
Bing Zhao4df82b52014-03-31 14:41:44 -0700239 .support_pscan_win_report = false,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700240 .sd_blksz_fw_dl = 64,
Xinming Hudc759612014-11-24 02:40:53 -0800241 .supports_fw_dump = false,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700242};
243
244static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
245 .helper = NULL,
246 .firmware = "mrvl/sd8787_uapsta.bin",
Bing Zhao2ac654f2011-11-16 20:40:42 -0800247 .reg = &btmrvl_reg_87xx,
Bing Zhao4df82b52014-03-31 14:41:44 -0700248 .support_pscan_win_report = false,
Bing Zhao2ac654f2011-11-16 20:40:42 -0800249 .sd_blksz_fw_dl = 256,
Xinming Hudc759612014-11-24 02:40:53 -0800250 .supports_fw_dump = false,
Bing Zhao2ac654f2011-11-16 20:40:42 -0800251};
252
253static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
254 .helper = NULL,
255 .firmware = "mrvl/sd8797_uapsta.bin",
256 .reg = &btmrvl_reg_87xx,
Bing Zhao4df82b52014-03-31 14:41:44 -0700257 .support_pscan_win_report = false,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700258 .sd_blksz_fw_dl = 256,
Xinming Hudc759612014-11-24 02:40:53 -0800259 .supports_fw_dump = false,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200260};
261
Xinming Hu3907d552014-09-30 06:45:33 -0400262static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
263 .helper = NULL,
264 .firmware = "mrvl/sd8887_uapsta.bin",
265 .reg = &btmrvl_reg_8887,
266 .support_pscan_win_report = true,
267 .sd_blksz_fw_dl = 256,
Xinming Hudc759612014-11-24 02:40:53 -0800268 .supports_fw_dump = false,
Xinming Hu3907d552014-09-30 06:45:33 -0400269};
270
Bing Zhao22f2efe2013-05-13 18:15:32 -0700271static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
272 .helper = NULL,
273 .firmware = "mrvl/sd8897_uapsta.bin",
Amitkumar Karwar1e3e4922014-09-30 06:45:32 -0400274 .reg = &btmrvl_reg_8897,
Bing Zhao4df82b52014-03-31 14:41:44 -0700275 .support_pscan_win_report = true,
Bing Zhao22f2efe2013-05-13 18:15:32 -0700276 .sd_blksz_fw_dl = 256,
Xinming Hudc759612014-11-24 02:40:53 -0800277 .supports_fw_dump = true,
Bing Zhao22f2efe2013-05-13 18:15:32 -0700278};
279
Amitkumar Karwarf0ef6742015-09-21 03:06:42 -0700280static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
281 .helper = NULL,
282 .firmware = "mrvl/sd8997_uapsta.bin",
283 .reg = &btmrvl_reg_8997,
284 .support_pscan_win_report = true,
285 .sd_blksz_fw_dl = 256,
286 .supports_fw_dump = true,
287};
288
Bing Zhao789221e2009-06-02 14:29:36 -0700289static const struct sdio_device_id btmrvl_sdio_ids[] = {
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200290 /* Marvell SD8688 Bluetooth device */
291 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
Amitkumar Karwar53d6cfa2015-09-21 03:06:41 -0700292 .driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700293 /* Marvell SD8787 Bluetooth device */
294 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
Amitkumar Karwar53d6cfa2015-09-21 03:06:41 -0700295 .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
Bing Zhao37ed5612012-05-23 18:50:04 -0700296 /* Marvell SD8787 Bluetooth AMP device */
297 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
Amitkumar Karwar53d6cfa2015-09-21 03:06:41 -0700298 .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
Bing Zhao2ac654f2011-11-16 20:40:42 -0800299 /* Marvell SD8797 Bluetooth device */
300 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
Amitkumar Karwar53d6cfa2015-09-21 03:06:41 -0700301 .driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
Xinming Hu3907d552014-09-30 06:45:33 -0400302 /* Marvell SD8887 Bluetooth device */
303 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
304 .driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
Bing Zhao22f2efe2013-05-13 18:15:32 -0700305 /* Marvell SD8897 Bluetooth device */
306 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
Amitkumar Karwar53d6cfa2015-09-21 03:06:41 -0700307 .driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
Amitkumar Karwarf0ef6742015-09-21 03:06:42 -0700308 /* Marvell SD8997 Bluetooth device */
309 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
310 .driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200311
312 { } /* Terminating entry */
Bing Zhao789221e2009-06-02 14:29:36 -0700313};
314
315MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
316
Bing Zhao789221e2009-06-02 14:29:36 -0700317static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
318{
319 u8 reg;
320 int ret;
321
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700322 reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700323 if (!ret)
324 card->rx_unit = reg;
325
Bing Zhao789221e2009-06-02 14:29:36 -0700326 return ret;
327}
328
329static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
330{
Bing Zhao789221e2009-06-02 14:29:36 -0700331 u8 fws0, fws1;
Marcel Holtmann93742532009-06-13 07:40:18 +0200332 int ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700333
334 *dat = 0;
335
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700336 fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
Kulikov Vasiliy278be272010-07-05 12:01:22 +0400337 if (ret)
338 return -EIO;
Bing Zhao789221e2009-06-02 14:29:36 -0700339
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700340 fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
Marcel Holtmann93742532009-06-13 07:40:18 +0200341 if (ret)
Bing Zhao789221e2009-06-02 14:29:36 -0700342 return -EIO;
Bing Zhao789221e2009-06-02 14:29:36 -0700343
344 *dat = (((u16) fws1) << 8) | fws0;
345
Bing Zhao789221e2009-06-02 14:29:36 -0700346 return 0;
347}
348
349static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
350{
Bing Zhao789221e2009-06-02 14:29:36 -0700351 u8 reg;
Marcel Holtmann93742532009-06-13 07:40:18 +0200352 int ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700353
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700354 reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700355 if (!ret)
356 *dat = (u16) reg << card->rx_unit;
357
Bing Zhao789221e2009-06-02 14:29:36 -0700358 return ret;
359}
360
361static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200362 u8 mask)
Bing Zhao789221e2009-06-02 14:29:36 -0700363{
364 int ret;
365
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700366 sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700367 if (ret) {
368 BT_ERR("Unable to enable the host interrupt!");
369 ret = -EIO;
370 }
371
Bing Zhao789221e2009-06-02 14:29:36 -0700372 return ret;
373}
374
375static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200376 u8 mask)
Bing Zhao789221e2009-06-02 14:29:36 -0700377{
Bing Zhao789221e2009-06-02 14:29:36 -0700378 u8 host_int_mask;
Marcel Holtmann93742532009-06-13 07:40:18 +0200379 int ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700380
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700381 host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
Marcel Holtmann93742532009-06-13 07:40:18 +0200382 if (ret)
383 return -EIO;
Bing Zhao789221e2009-06-02 14:29:36 -0700384
385 host_int_mask &= ~mask;
386
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700387 sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700388 if (ret < 0) {
389 BT_ERR("Unable to disable the host interrupt!");
Marcel Holtmann93742532009-06-13 07:40:18 +0200390 return -EIO;
Bing Zhao789221e2009-06-02 14:29:36 -0700391 }
392
Marcel Holtmann93742532009-06-13 07:40:18 +0200393 return 0;
Bing Zhao789221e2009-06-02 14:29:36 -0700394}
395
396static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
397{
398 unsigned int tries;
Bing Zhao789221e2009-06-02 14:29:36 -0700399 u8 status;
Marcel Holtmann93742532009-06-13 07:40:18 +0200400 int ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700401
402 for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700403 status = sdio_readb(card->func, card->reg->card_status, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700404 if (ret)
405 goto failed;
406 if ((status & bits) == bits)
Marcel Holtmann93742532009-06-13 07:40:18 +0200407 return ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700408
409 udelay(1);
410 }
411
412 ret = -ETIMEDOUT;
413
414failed:
415 BT_ERR("FAILED! ret=%d", ret);
416
Bing Zhao789221e2009-06-02 14:29:36 -0700417 return ret;
418}
419
420static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200421 int pollnum)
Bing Zhao789221e2009-06-02 14:29:36 -0700422{
Bing Zhao789221e2009-06-02 14:29:36 -0700423 u16 firmwarestat;
Andreas Fenkart69676b12013-04-22 11:10:23 +0200424 int tries, ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700425
Bing Zhao789221e2009-06-02 14:29:36 -0700426 /* Wait for firmware to become ready */
427 for (tries = 0; tries < pollnum; tries++) {
Andreas Fenkartc1c999e2013-04-22 11:10:22 +0200428 sdio_claim_host(card->func);
429 ret = btmrvl_sdio_read_fw_status(card, &firmwarestat);
430 sdio_release_host(card->func);
431 if (ret < 0)
Bing Zhao789221e2009-06-02 14:29:36 -0700432 continue;
433
Andreas Fenkart69676b12013-04-22 11:10:23 +0200434 if (firmwarestat == FIRMWARE_READY)
435 return 0;
436
Wei-Ning Huang9a012422016-03-08 11:40:06 +0800437 msleep(100);
Bing Zhao789221e2009-06-02 14:29:36 -0700438 }
439
Andreas Fenkart69676b12013-04-22 11:10:23 +0200440 return -ETIMEDOUT;
Bing Zhao789221e2009-06-02 14:29:36 -0700441}
442
443static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
444{
445 const struct firmware *fw_helper = NULL;
446 const u8 *helper = NULL;
447 int ret;
448 void *tmphlprbuf = NULL;
449 int tmphlprbufsz, hlprblknow, helperlen;
450 u8 *helperbuf;
451 u32 tx_len;
452
Bing Zhao789221e2009-06-02 14:29:36 -0700453 ret = request_firmware(&fw_helper, card->helper,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200454 &card->func->dev);
Bing Zhao789221e2009-06-02 14:29:36 -0700455 if ((ret < 0) || !fw_helper) {
456 BT_ERR("request_firmware(helper) failed, error code = %d",
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200457 ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700458 ret = -ENOENT;
459 goto done;
460 }
461
462 helper = fw_helper->data;
463 helperlen = fw_helper->size;
464
465 BT_DBG("Downloading helper image (%d bytes), block size %d bytes",
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200466 helperlen, SDIO_BLOCK_SIZE);
Bing Zhao789221e2009-06-02 14:29:36 -0700467
468 tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
469
Julia Lawallf8df39f2010-05-13 22:02:03 +0200470 tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
Bing Zhao789221e2009-06-02 14:29:36 -0700471 if (!tmphlprbuf) {
472 BT_ERR("Unable to allocate buffer for helper."
473 " Terminating download");
474 ret = -ENOMEM;
475 goto done;
476 }
477
Bing Zhao789221e2009-06-02 14:29:36 -0700478 helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
479
480 /* Perform helper data transfer */
481 tx_len = (FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE)
482 - SDIO_HEADER_LEN;
483 hlprblknow = 0;
484
485 do {
486 ret = btmrvl_sdio_poll_card_status(card,
487 CARD_IO_READY | DN_LD_CARD_RDY);
488 if (ret < 0) {
489 BT_ERR("Helper download poll status timeout @ %d",
490 hlprblknow);
491 goto done;
492 }
493
494 /* Check if there is more data? */
495 if (hlprblknow >= helperlen)
496 break;
497
498 if (helperlen - hlprblknow < tx_len)
499 tx_len = helperlen - hlprblknow;
500
501 /* Little-endian */
502 helperbuf[0] = ((tx_len & 0x000000ff) >> 0);
503 helperbuf[1] = ((tx_len & 0x0000ff00) >> 8);
504 helperbuf[2] = ((tx_len & 0x00ff0000) >> 16);
505 helperbuf[3] = ((tx_len & 0xff000000) >> 24);
506
507 memcpy(&helperbuf[SDIO_HEADER_LEN], &helper[hlprblknow],
508 tx_len);
509
510 /* Now send the data */
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200511 ret = sdio_writesb(card->func, card->ioport, helperbuf,
512 FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE);
Bing Zhao789221e2009-06-02 14:29:36 -0700513 if (ret < 0) {
514 BT_ERR("IO error during helper download @ %d",
515 hlprblknow);
516 goto done;
517 }
518
519 hlprblknow += tx_len;
520 } while (true);
521
522 BT_DBG("Transferring helper image EOF block");
523
524 memset(helperbuf, 0x0, SDIO_BLOCK_SIZE);
525
526 ret = sdio_writesb(card->func, card->ioport, helperbuf,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200527 SDIO_BLOCK_SIZE);
Bing Zhao789221e2009-06-02 14:29:36 -0700528 if (ret < 0) {
529 BT_ERR("IO error in writing helper image EOF block");
530 goto done;
531 }
532
533 ret = 0;
534
535done:
536 kfree(tmphlprbuf);
Jesper Juhl59f34fb2012-04-09 22:49:49 +0200537 release_firmware(fw_helper);
Bing Zhao789221e2009-06-02 14:29:36 -0700538 return ret;
539}
540
541static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
542{
543 const struct firmware *fw_firmware = NULL;
544 const u8 *firmware = NULL;
545 int firmwarelen, tmpfwbufsz, ret;
546 unsigned int tries, offset;
547 u8 base0, base1;
548 void *tmpfwbuf = NULL;
549 u8 *fwbuf;
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700550 u16 len, blksz_dl = card->sd_blksz_fw_dl;
Bing Zhao789221e2009-06-02 14:29:36 -0700551 int txlen = 0, tx_blocks = 0, count = 0;
552
Bing Zhao789221e2009-06-02 14:29:36 -0700553 ret = request_firmware(&fw_firmware, card->firmware,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200554 &card->func->dev);
Bing Zhao789221e2009-06-02 14:29:36 -0700555 if ((ret < 0) || !fw_firmware) {
556 BT_ERR("request_firmware(firmware) failed, error code = %d",
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200557 ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700558 ret = -ENOENT;
559 goto done;
560 }
561
562 firmware = fw_firmware->data;
563 firmwarelen = fw_firmware->size;
564
565 BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
566
567 tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
Julia Lawallf8df39f2010-05-13 22:02:03 +0200568 tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
Bing Zhao789221e2009-06-02 14:29:36 -0700569 if (!tmpfwbuf) {
570 BT_ERR("Unable to allocate buffer for firmware."
571 " Terminating download");
572 ret = -ENOMEM;
573 goto done;
574 }
575
Bing Zhao789221e2009-06-02 14:29:36 -0700576 /* Ensure aligned firmware buffer */
577 fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
578
579 /* Perform firmware data transfer */
580 offset = 0;
581 do {
582 ret = btmrvl_sdio_poll_card_status(card,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200583 CARD_IO_READY | DN_LD_CARD_RDY);
Bing Zhao789221e2009-06-02 14:29:36 -0700584 if (ret < 0) {
585 BT_ERR("FW download with helper poll status"
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200586 " timeout @ %d", offset);
Bing Zhao789221e2009-06-02 14:29:36 -0700587 goto done;
588 }
589
590 /* Check if there is more data ? */
591 if (offset >= firmwarelen)
592 break;
593
594 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
595 base0 = sdio_readb(card->func,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700596 card->reg->sq_read_base_addr_a0, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700597 if (ret) {
598 BT_ERR("BASE0 register read failed:"
599 " base0 = 0x%04X(%d)."
600 " Terminating download",
601 base0, base0);
602 ret = -EIO;
603 goto done;
604 }
605 base1 = sdio_readb(card->func,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700606 card->reg->sq_read_base_addr_a1, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700607 if (ret) {
608 BT_ERR("BASE1 register read failed:"
609 " base1 = 0x%04X(%d)."
610 " Terminating download",
611 base1, base1);
612 ret = -EIO;
613 goto done;
614 }
615
616 len = (((u16) base1) << 8) | base0;
617 if (len)
618 break;
619
620 udelay(10);
621 }
622
623 if (!len)
624 break;
625 else if (len > BTM_UPLD_SIZE) {
626 BT_ERR("FW download failure @%d, invalid length %d",
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200627 offset, len);
Bing Zhao789221e2009-06-02 14:29:36 -0700628 ret = -EINVAL;
629 goto done;
630 }
631
632 txlen = len;
633
634 if (len & BIT(0)) {
635 count++;
636 if (count > MAX_WRITE_IOMEM_RETRY) {
637 BT_ERR("FW download failure @%d, "
638 "over max retry count", offset);
639 ret = -EIO;
640 goto done;
641 }
642 BT_ERR("FW CRC error indicated by the helper: "
643 "len = 0x%04X, txlen = %d", len, txlen);
644 len &= ~BIT(0);
645 /* Set txlen to 0 so as to resend from same offset */
646 txlen = 0;
647 } else {
648 count = 0;
649
650 /* Last block ? */
651 if (firmwarelen - offset < txlen)
652 txlen = firmwarelen - offset;
653
Andy Shevchenkoba34dd32013-08-02 14:10:12 +0300654 tx_blocks = DIV_ROUND_UP(txlen, blksz_dl);
Bing Zhao789221e2009-06-02 14:29:36 -0700655
656 memcpy(fwbuf, &firmware[offset], txlen);
657 }
658
659 ret = sdio_writesb(card->func, card->ioport, fwbuf,
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700660 tx_blocks * blksz_dl);
Bing Zhao789221e2009-06-02 14:29:36 -0700661
662 if (ret < 0) {
663 BT_ERR("FW download, writesb(%d) failed @%d",
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200664 count, offset);
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700665 sdio_writeb(card->func, HOST_CMD53_FIN,
666 card->reg->cfg, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700667 if (ret)
668 BT_ERR("writeb failed (CFG)");
669 }
670
671 offset += txlen;
672 } while (true);
673
Amitkumar Karwar1c6098e2015-01-01 00:13:42 -0800674 BT_INFO("FW download over, size %d bytes", offset);
Bing Zhao789221e2009-06-02 14:29:36 -0700675
676 ret = 0;
677
678done:
679 kfree(tmpfwbuf);
Jesper Juhl59f34fb2012-04-09 22:49:49 +0200680 release_firmware(fw_firmware);
Bing Zhao789221e2009-06-02 14:29:36 -0700681 return ret;
682}
683
684static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
685{
686 u16 buf_len = 0;
Andrei Emeltchenko42632802012-09-28 14:36:08 +0300687 int ret, num_blocks, blksz;
Bing Zhao789221e2009-06-02 14:29:36 -0700688 struct sk_buff *skb = NULL;
689 u32 type;
690 u8 *payload = NULL;
691 struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
692 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
693
Bing Zhao789221e2009-06-02 14:29:36 -0700694 if (!card || !card->func) {
695 BT_ERR("card or function is NULL!");
696 ret = -EINVAL;
697 goto exit;
698 }
699
700 /* Read the length of data to be transferred */
701 ret = btmrvl_sdio_read_rx_len(card, &buf_len);
702 if (ret < 0) {
703 BT_ERR("read rx_len failed");
704 ret = -EIO;
705 goto exit;
706 }
707
708 blksz = SDIO_BLOCK_SIZE;
Andrei Emeltchenkoe678bad2012-09-28 14:36:09 +0300709 num_blocks = DIV_ROUND_UP(buf_len, blksz);
Bing Zhao789221e2009-06-02 14:29:36 -0700710
711 if (buf_len <= SDIO_HEADER_LEN
Andrei Emeltchenko42632802012-09-28 14:36:08 +0300712 || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
Bing Zhao789221e2009-06-02 14:29:36 -0700713 BT_ERR("invalid packet length: %d", buf_len);
714 ret = -EINVAL;
715 goto exit;
716 }
717
718 /* Allocate buffer */
Andrei Emeltchenko42632802012-09-28 14:36:08 +0300719 skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
Prasanna Karthik1f438c62015-09-25 09:03:14 +0000720 if (!skb) {
Bing Zhao789221e2009-06-02 14:29:36 -0700721 BT_ERR("No free skb");
Wei Yongjun6ea81c42013-06-05 10:16:55 +0800722 ret = -ENOMEM;
Bing Zhao789221e2009-06-02 14:29:36 -0700723 goto exit;
724 }
725
Bing Zhao3318b232009-07-08 11:44:14 -0700726 if ((unsigned long) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
727 skb_put(skb, (unsigned long) skb->data &
728 (BTSDIO_DMA_ALIGN - 1));
729 skb_pull(skb, (unsigned long) skb->data &
730 (BTSDIO_DMA_ALIGN - 1));
Bing Zhao789221e2009-06-02 14:29:36 -0700731 }
732
Bing Zhao3318b232009-07-08 11:44:14 -0700733 payload = skb->data;
Bing Zhao789221e2009-06-02 14:29:36 -0700734
735 ret = sdio_readsb(card->func, payload, card->ioport,
Andrei Emeltchenko42632802012-09-28 14:36:08 +0300736 num_blocks * blksz);
Bing Zhao789221e2009-06-02 14:29:36 -0700737 if (ret < 0) {
738 BT_ERR("readsb failed: %d", ret);
739 ret = -EIO;
740 goto exit;
741 }
742
743 /* This is SDIO specific header length: byte[2][1][0], type: byte[3]
744 * (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
745 */
746
747 buf_len = payload[0];
Andrei Emeltchenko9cb23dd2012-09-28 14:36:10 +0300748 buf_len |= payload[1] << 8;
749 buf_len |= payload[2] << 16;
750
751 if (buf_len > blksz * num_blocks) {
752 BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
753 buf_len, blksz * num_blocks);
754 ret = -EIO;
755 goto exit;
756 }
757
Bing Zhao789221e2009-06-02 14:29:36 -0700758 type = payload[3];
759
760 switch (type) {
761 case HCI_ACLDATA_PKT:
762 case HCI_SCODATA_PKT:
763 case HCI_EVENT_PKT:
Marcel Holtmann618e8bc2015-11-05 07:33:56 +0100764 hci_skb_pkt_type(skb) = type;
Bing Zhao789221e2009-06-02 14:29:36 -0700765 skb_put(skb, buf_len);
766 skb_pull(skb, SDIO_HEADER_LEN);
767
Andrei Emeltchenkoea1e76a2012-06-13 13:35:44 +0300768 if (type == HCI_EVENT_PKT) {
769 if (btmrvl_check_evtpkt(priv, skb))
Marcel Holtmanne1a26172013-10-10 16:52:43 -0700770 hci_recv_frame(hdev, skb);
Andrei Emeltchenko2c2453f2012-07-09 13:57:18 +0300771 } else {
Marcel Holtmanne1a26172013-10-10 16:52:43 -0700772 hci_recv_frame(hdev, skb);
Andrei Emeltchenko2c2453f2012-07-09 13:57:18 +0300773 }
Bing Zhao789221e2009-06-02 14:29:36 -0700774
Bing Zhao789221e2009-06-02 14:29:36 -0700775 hdev->stat.byte_rx += buf_len;
776 break;
777
778 case MRVL_VENDOR_PKT:
Marcel Holtmann618e8bc2015-11-05 07:33:56 +0100779 hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
Bing Zhao789221e2009-06-02 14:29:36 -0700780 skb_put(skb, buf_len);
781 skb_pull(skb, SDIO_HEADER_LEN);
782
783 if (btmrvl_process_event(priv, skb))
Marcel Holtmanne1a26172013-10-10 16:52:43 -0700784 hci_recv_frame(hdev, skb);
Bing Zhao789221e2009-06-02 14:29:36 -0700785
786 hdev->stat.byte_rx += buf_len;
787 break;
788
789 default:
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200790 BT_ERR("Unknown packet type:%d", type);
Andrei Emeltchenko78c1b8e2012-10-10 17:41:33 +0300791 BT_ERR("hex: %*ph", blksz * num_blocks, payload);
Bing Zhao789221e2009-06-02 14:29:36 -0700792
793 kfree_skb(skb);
794 skb = NULL;
795 break;
796 }
797
798exit:
799 if (ret) {
800 hdev->stat.err_rx++;
Wei Yongjun79232962012-08-28 21:12:48 +0800801 kfree_skb(skb);
Bing Zhao789221e2009-06-02 14:29:36 -0700802 }
803
Bing Zhao789221e2009-06-02 14:29:36 -0700804 return ret;
805}
806
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700807static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
Bing Zhao789221e2009-06-02 14:29:36 -0700808{
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700809 ulong flags;
810 u8 ireg;
Bing Zhao789221e2009-06-02 14:29:36 -0700811 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
812
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700813 spin_lock_irqsave(&priv->driver_lock, flags);
814 ireg = sdio_ireg;
815 sdio_ireg = 0;
816 spin_unlock_irqrestore(&priv->driver_lock, flags);
Bing Zhao789221e2009-06-02 14:29:36 -0700817
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700818 sdio_claim_host(card->func);
819 if (ireg & DN_LD_HOST_INT_STATUS) {
Bing Zhao789221e2009-06-02 14:29:36 -0700820 if (priv->btmrvl_dev.tx_dnld_rdy)
821 BT_DBG("tx_done already received: "
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700822 " int_status=0x%x", ireg);
Bing Zhao789221e2009-06-02 14:29:36 -0700823 else
824 priv->btmrvl_dev.tx_dnld_rdy = true;
825 }
826
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700827 if (ireg & UP_LD_HOST_INT_STATUS)
Bing Zhao789221e2009-06-02 14:29:36 -0700828 btmrvl_sdio_card_to_host(priv);
829
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700830 sdio_release_host(card->func);
Bing Zhao789221e2009-06-02 14:29:36 -0700831
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700832 return 0;
Bing Zhao789221e2009-06-02 14:29:36 -0700833}
834
Bing Zhao0d367402014-03-28 14:54:39 -0700835static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
836{
837 struct btmrvl_adapter *adapter = card->priv->adapter;
838 int ret;
839
840 ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE);
841 if (ret) {
842 BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret);
843 return ret;
844 }
845
846 *ireg = adapter->hw_regs[card->reg->host_intstatus];
847 BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg);
848
849 return 0;
850}
851
Bing Zhao8af48402014-03-27 21:30:42 -0700852static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
853{
854 int ret;
855
856 *ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
857 if (ret) {
858 BT_ERR("sdio_readb: read int status failed: %d", ret);
859 return ret;
860 }
861
862 if (*ireg) {
863 /*
864 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
865 * Clear the interrupt status register and re-enable the
866 * interrupt.
867 */
868 BT_DBG("int_status = 0x%x", *ireg);
869
870 sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS |
871 UP_LD_HOST_INT_STATUS),
872 card->reg->host_intstatus, &ret);
873 if (ret) {
874 BT_ERR("sdio_writeb: clear int status failed: %d", ret);
875 return ret;
876 }
877 }
878
879 return 0;
880}
881
Bing Zhao789221e2009-06-02 14:29:36 -0700882static void btmrvl_sdio_interrupt(struct sdio_func *func)
883{
884 struct btmrvl_private *priv;
Bing Zhao789221e2009-06-02 14:29:36 -0700885 struct btmrvl_sdio_card *card;
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700886 ulong flags;
Bing Zhao789221e2009-06-02 14:29:36 -0700887 u8 ireg = 0;
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700888 int ret;
Bing Zhao789221e2009-06-02 14:29:36 -0700889
Bing Zhao789221e2009-06-02 14:29:36 -0700890 card = sdio_get_drvdata(func);
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700891 if (!card || !card->priv) {
Amitkumar Karwar7365d472014-11-24 02:40:52 -0800892 BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
893 func, card);
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700894 return;
Bing Zhao789221e2009-06-02 14:29:36 -0700895 }
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700896
897 priv = card->priv;
898
Amitkumar Karwar7b4b8742015-01-01 00:13:41 -0800899 if (priv->surprise_removed)
900 return;
901
Bing Zhao0d367402014-03-28 14:54:39 -0700902 if (card->reg->int_read_to_clear)
903 ret = btmrvl_sdio_read_to_clear(card, &ireg);
904 else
905 ret = btmrvl_sdio_write_to_clear(card, &ireg);
906
Bing Zhao8af48402014-03-27 21:30:42 -0700907 if (ret)
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700908 return;
Amitkumar Karward1d10d72010-05-27 16:38:37 -0700909
910 spin_lock_irqsave(&priv->driver_lock, flags);
911 sdio_ireg |= ireg;
912 spin_unlock_irqrestore(&priv->driver_lock, flags);
913
914 btmrvl_interrupt(priv);
Bing Zhao789221e2009-06-02 14:29:36 -0700915}
916
917static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
918{
Bing Zhao789221e2009-06-02 14:29:36 -0700919 struct sdio_func *func;
Marcel Holtmanndcf47f32009-06-09 16:21:58 +0200920 u8 reg;
921 int ret = 0;
Bing Zhao789221e2009-06-02 14:29:36 -0700922
Bing Zhao789221e2009-06-02 14:29:36 -0700923 if (!card || !card->func) {
924 BT_ERR("Error: card or function is NULL!");
925 ret = -EINVAL;
926 goto failed;
927 }
928
929 func = card->func;
930
Bing Zhao789221e2009-06-02 14:29:36 -0700931 sdio_claim_host(func);
932
933 ret = sdio_enable_func(func);
934 if (ret) {
935 BT_ERR("sdio_enable_func() failed: ret=%d", ret);
936 ret = -EIO;
937 goto release_host;
938 }
939
940 ret = sdio_claim_irq(func, btmrvl_sdio_interrupt);
941 if (ret) {
942 BT_ERR("sdio_claim_irq failed: ret=%d", ret);
943 ret = -EIO;
944 goto disable_func;
945 }
946
947 ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE);
948 if (ret) {
949 BT_ERR("cannot set SDIO block size");
950 ret = -EIO;
951 goto release_irq;
952 }
953
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700954 reg = sdio_readb(func, card->reg->io_port_0, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700955 if (ret < 0) {
956 ret = -EIO;
957 goto release_irq;
958 }
959
960 card->ioport = reg;
961
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700962 reg = sdio_readb(func, card->reg->io_port_1, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700963 if (ret < 0) {
964 ret = -EIO;
965 goto release_irq;
966 }
967
968 card->ioport |= (reg << 8);
969
Kevin Gan9f72c1d2011-04-08 18:19:33 -0700970 reg = sdio_readb(func, card->reg->io_port_2, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -0700971 if (ret < 0) {
972 ret = -EIO;
973 goto release_irq;
974 }
975
976 card->ioport |= (reg << 16);
977
978 BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
979
Bing Zhao0d367402014-03-28 14:54:39 -0700980 if (card->reg->int_read_to_clear) {
981 reg = sdio_readb(func, card->reg->host_int_rsr, &ret);
982 if (ret < 0) {
983 ret = -EIO;
984 goto release_irq;
985 }
986 sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret);
987 if (ret < 0) {
988 ret = -EIO;
989 goto release_irq;
990 }
991
992 reg = sdio_readb(func, card->reg->card_misc_cfg, &ret);
993 if (ret < 0) {
994 ret = -EIO;
995 goto release_irq;
996 }
997 sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret);
998 if (ret < 0) {
999 ret = -EIO;
1000 goto release_irq;
1001 }
1002 }
1003
Bing Zhao789221e2009-06-02 14:29:36 -07001004 sdio_set_drvdata(func, card);
1005
1006 sdio_release_host(func);
1007
Bing Zhao789221e2009-06-02 14:29:36 -07001008 return 0;
1009
1010release_irq:
1011 sdio_release_irq(func);
1012
1013disable_func:
1014 sdio_disable_func(func);
1015
1016release_host:
1017 sdio_release_host(func);
1018
1019failed:
Bing Zhao789221e2009-06-02 14:29:36 -07001020 return ret;
1021}
1022
1023static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
1024{
Bing Zhao789221e2009-06-02 14:29:36 -07001025 if (card && card->func) {
1026 sdio_claim_host(card->func);
1027 sdio_release_irq(card->func);
1028 sdio_disable_func(card->func);
1029 sdio_release_host(card->func);
1030 sdio_set_drvdata(card->func, NULL);
1031 }
1032
Bing Zhao789221e2009-06-02 14:29:36 -07001033 return 0;
1034}
1035
1036static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
1037{
1038 int ret;
1039
Marcel Holtmann93742532009-06-13 07:40:18 +02001040 if (!card || !card->func)
Bing Zhao789221e2009-06-02 14:29:36 -07001041 return -EINVAL;
Bing Zhao789221e2009-06-02 14:29:36 -07001042
1043 sdio_claim_host(card->func);
1044
1045 ret = btmrvl_sdio_enable_host_int_mask(card, HIM_ENABLE);
1046
1047 btmrvl_sdio_get_rx_unit(card);
1048
1049 sdio_release_host(card->func);
1050
Bing Zhao789221e2009-06-02 14:29:36 -07001051 return ret;
1052}
1053
1054static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
1055{
1056 int ret;
1057
Marcel Holtmann93742532009-06-13 07:40:18 +02001058 if (!card || !card->func)
Bing Zhao789221e2009-06-02 14:29:36 -07001059 return -EINVAL;
Bing Zhao789221e2009-06-02 14:29:36 -07001060
1061 sdio_claim_host(card->func);
1062
1063 ret = btmrvl_sdio_disable_host_int_mask(card, HIM_DISABLE);
1064
1065 sdio_release_host(card->func);
1066
Bing Zhao789221e2009-06-02 14:29:36 -07001067 return ret;
1068}
1069
1070static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
1071 u8 *payload, u16 nb)
1072{
1073 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1074 int ret = 0;
Bing Zhao789221e2009-06-02 14:29:36 -07001075 int blksz;
1076 int i = 0;
1077 u8 *buf = NULL;
1078 void *tmpbuf = NULL;
1079 int tmpbufsz;
1080
Bing Zhao789221e2009-06-02 14:29:36 -07001081 if (!card || !card->func) {
1082 BT_ERR("card or function is NULL!");
Bing Zhao789221e2009-06-02 14:29:36 -07001083 return -EINVAL;
1084 }
1085
Ricky Liangd2f30242016-06-28 15:06:57 +08001086 blksz = DIV_ROUND_UP(nb, SDIO_BLOCK_SIZE) * SDIO_BLOCK_SIZE;
1087
Bing Zhao789221e2009-06-02 14:29:36 -07001088 buf = payload;
Ricky Liangd2f30242016-06-28 15:06:57 +08001089 if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1) ||
1090 nb < blksz) {
1091 tmpbufsz = ALIGN_SZ(blksz, BTSDIO_DMA_ALIGN) +
1092 BTSDIO_DMA_ALIGN;
Julia Lawall59598092009-08-06 22:05:18 +02001093 tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL);
1094 if (!tmpbuf)
1095 return -ENOMEM;
Bing Zhao789221e2009-06-02 14:29:36 -07001096 buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN);
1097 memcpy(buf, payload, nb);
1098 }
1099
Bing Zhao789221e2009-06-02 14:29:36 -07001100 sdio_claim_host(card->func);
1101
1102 do {
1103 /* Transfer data to card */
1104 ret = sdio_writesb(card->func, card->ioport, buf,
Ricky Liangd2f30242016-06-28 15:06:57 +08001105 blksz);
Bing Zhao789221e2009-06-02 14:29:36 -07001106 if (ret < 0) {
1107 i++;
1108 BT_ERR("i=%d writesb failed: %d", i, ret);
Andrei Emeltchenko78c1b8e2012-10-10 17:41:33 +03001109 BT_ERR("hex: %*ph", nb, payload);
Bing Zhao789221e2009-06-02 14:29:36 -07001110 ret = -EIO;
1111 if (i > MAX_WRITE_IOMEM_RETRY)
1112 goto exit;
1113 }
1114 } while (ret);
1115
1116 priv->btmrvl_dev.tx_dnld_rdy = false;
1117
1118exit:
1119 sdio_release_host(card->func);
Yoichi Yuasa88d1a0c2010-02-04 09:55:51 +09001120 kfree(tmpbuf);
Bing Zhao789221e2009-06-02 14:29:36 -07001121
Bing Zhao789221e2009-06-02 14:29:36 -07001122 return ret;
1123}
1124
1125static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
1126{
Gustavo Padovanfaff7f72013-04-18 19:35:33 -03001127 int ret;
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001128 u8 fws0;
1129 int pollnum = MAX_POLL_TRIES;
Bing Zhao789221e2009-06-02 14:29:36 -07001130
Bing Zhao789221e2009-06-02 14:29:36 -07001131 if (!card || !card->func) {
1132 BT_ERR("card or function is NULL!");
Bing Zhao789221e2009-06-02 14:29:36 -07001133 return -EINVAL;
1134 }
Bing Zhao789221e2009-06-02 14:29:36 -07001135
1136 if (!btmrvl_sdio_verify_fw_download(card, 1)) {
1137 BT_DBG("Firmware already downloaded!");
Andreas Fenkartc1c999e2013-04-22 11:10:22 +02001138 return 0;
Bing Zhao789221e2009-06-02 14:29:36 -07001139 }
1140
Andreas Fenkartc1c999e2013-04-22 11:10:22 +02001141 sdio_claim_host(card->func);
1142
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001143 /* Check if other function driver is downloading the firmware */
1144 fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -07001145 if (ret) {
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001146 BT_ERR("Failed to read FW downloading status!");
Bing Zhao789221e2009-06-02 14:29:36 -07001147 ret = -EIO;
1148 goto done;
1149 }
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001150 if (fws0) {
1151 BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
Bing Zhao789221e2009-06-02 14:29:36 -07001152
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001153 /* Give other function more time to download the firmware */
1154 pollnum *= 10;
1155 } else {
1156 if (card->helper) {
1157 ret = btmrvl_sdio_download_helper(card);
1158 if (ret) {
1159 BT_ERR("Failed to download helper!");
1160 ret = -EIO;
1161 goto done;
1162 }
1163 }
1164
1165 if (btmrvl_sdio_download_fw_w_helper(card)) {
1166 BT_ERR("Failed to download firmware!");
1167 ret = -EIO;
1168 goto done;
1169 }
Bing Zhao789221e2009-06-02 14:29:36 -07001170 }
1171
Andreas Fenkart69676b12013-04-22 11:10:23 +02001172 /*
1173 * winner or not, with this test the FW synchronizes when the
1174 * module can continue its initialization
1175 */
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001176 if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
Bing Zhao789221e2009-06-02 14:29:36 -07001177 BT_ERR("FW failed to be active in time!");
Chin-Ran Lo86f7ac72015-12-29 04:26:33 -08001178 ret = -ETIMEDOUT;
1179 goto done;
Bing Zhao789221e2009-06-02 14:29:36 -07001180 }
1181
Aniket Nagarnaik4863e4c2015-08-06 03:43:09 -07001182 sdio_release_host(card->func);
1183
Andreas Fenkartc1c999e2013-04-22 11:10:22 +02001184 return 0;
1185
Bing Zhao789221e2009-06-02 14:29:36 -07001186done:
1187 sdio_release_host(card->func);
Bing Zhao789221e2009-06-02 14:29:36 -07001188 return ret;
1189}
1190
1191static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
1192{
1193 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1194 int ret = 0;
1195
Bing Zhao789221e2009-06-02 14:29:36 -07001196 if (!card || !card->func) {
1197 BT_ERR("card or function is NULL!");
Bing Zhao789221e2009-06-02 14:29:36 -07001198 return -EINVAL;
1199 }
1200
1201 sdio_claim_host(card->func);
1202
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001203 sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
Bing Zhao789221e2009-06-02 14:29:36 -07001204
1205 sdio_release_host(card->func);
1206
1207 BT_DBG("wake up firmware");
1208
Bing Zhao789221e2009-06-02 14:29:36 -07001209 return ret;
1210}
1211
Xinming Hudc759612014-11-24 02:40:53 -08001212static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
1213{
1214 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1215 int ret = 0;
1216 unsigned int reg, reg_start, reg_end;
1217 char buf[256], *ptr;
1218 u8 loop, func, data;
1219 int MAX_LOOP = 2;
1220
1221 btmrvl_sdio_wakeup_fw(priv);
1222 sdio_claim_host(card->func);
1223
1224 for (loop = 0; loop < MAX_LOOP; loop++) {
1225 memset(buf, 0, sizeof(buf));
1226 ptr = buf;
1227
1228 if (loop == 0) {
1229 /* Read the registers of SDIO function0 */
1230 func = loop;
1231 reg_start = 0;
1232 reg_end = 9;
1233 } else {
1234 func = 2;
1235 reg_start = 0;
1236 reg_end = 0x09;
1237 }
1238
1239 ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
1240 func, reg_start, reg_end);
1241 for (reg = reg_start; reg <= reg_end; reg++) {
1242 if (func == 0)
1243 data = sdio_f0_readb(card->func, reg, &ret);
1244 else
1245 data = sdio_readb(card->func, reg, &ret);
1246
1247 if (!ret) {
1248 ptr += sprintf(ptr, "%02x ", data);
1249 } else {
1250 ptr += sprintf(ptr, "ERR");
1251 break;
1252 }
1253 }
1254
1255 BT_INFO("%s", buf);
1256 }
1257
1258 sdio_release_host(card->func);
1259}
1260
1261/* This function read/write firmware */
1262static enum
1263rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
1264 u8 doneflag)
1265{
1266 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1267 int ret, tries;
1268 u8 ctrl_data = 0;
1269
1270 sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
1271 &ret);
1272
1273 if (ret) {
1274 BT_ERR("SDIO write err");
1275 return RDWR_STATUS_FAILURE;
1276 }
1277
1278 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1279 ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
1280 &ret);
1281
1282 if (ret) {
1283 BT_ERR("SDIO read err");
1284 return RDWR_STATUS_FAILURE;
1285 }
1286
1287 if (ctrl_data == FW_DUMP_DONE)
1288 break;
1289 if (doneflag && ctrl_data == doneflag)
1290 return RDWR_STATUS_DONE;
1291 if (ctrl_data != FW_DUMP_HOST_READY) {
1292 BT_INFO("The ctrl reg was changed, re-try again!");
1293 sdio_writeb(card->func, FW_DUMP_HOST_READY,
1294 card->reg->fw_dump_ctrl, &ret);
1295 if (ret) {
1296 BT_ERR("SDIO write err");
1297 return RDWR_STATUS_FAILURE;
1298 }
1299 }
1300 usleep_range(100, 200);
1301 }
1302
1303 if (ctrl_data == FW_DUMP_HOST_READY) {
1304 BT_ERR("Fail to pull ctrl_data");
1305 return RDWR_STATUS_FAILURE;
1306 }
1307
1308 return RDWR_STATUS_SUCCESS;
1309}
1310
1311/* This function dump sdio register and memory data */
1312static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
1313{
1314 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1315 int ret = 0;
1316 unsigned int reg, reg_start, reg_end;
1317 enum rdwr_status stat;
1318 u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
Xinming Hua1e85f042015-04-21 06:59:56 -07001319 u8 dump_num = 0, idx, i, read_reg, doneflag = 0;
Xinming Hudc759612014-11-24 02:40:53 -08001320 u32 memory_size, fw_dump_len = 0;
1321
1322 /* dump sdio register first */
1323 btmrvl_sdio_dump_regs(priv);
1324
1325 if (!card->supports_fw_dump) {
1326 BT_ERR("Firmware dump not supported for this card!");
1327 return;
1328 }
1329
1330 for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
1331 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1332
1333 if (entry->mem_ptr) {
1334 vfree(entry->mem_ptr);
1335 entry->mem_ptr = NULL;
1336 }
1337 entry->mem_size = 0;
1338 }
1339
1340 btmrvl_sdio_wakeup_fw(priv);
1341 sdio_claim_host(card->func);
1342
1343 BT_INFO("== btmrvl firmware dump start ==");
1344
1345 stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1346 if (stat == RDWR_STATUS_FAILURE)
1347 goto done;
1348
1349 reg = card->reg->fw_dump_start;
1350 /* Read the number of the memories which will dump */
1351 dump_num = sdio_readb(card->func, reg, &ret);
1352
1353 if (ret) {
1354 BT_ERR("SDIO read memory length err");
1355 goto done;
1356 }
1357
1358 /* Read the length of every memory which will dump */
1359 for (idx = 0; idx < dump_num; idx++) {
1360 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1361
1362 stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1363 if (stat == RDWR_STATUS_FAILURE)
1364 goto done;
1365
1366 memory_size = 0;
1367 reg = card->reg->fw_dump_start;
1368 for (i = 0; i < 4; i++) {
1369 read_reg = sdio_readb(card->func, reg, &ret);
1370 if (ret) {
1371 BT_ERR("SDIO read err");
1372 goto done;
1373 }
1374 memory_size |= (read_reg << i*8);
1375 reg++;
1376 }
1377
1378 if (memory_size == 0) {
1379 BT_INFO("Firmware dump finished!");
Nachiket Kukade475b9ea2015-09-18 06:40:40 -07001380 sdio_writeb(card->func, FW_DUMP_READ_DONE,
1381 card->reg->fw_dump_ctrl, &ret);
1382 if (ret) {
1383 BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
1384 goto done;
1385 }
Xinming Hudc759612014-11-24 02:40:53 -08001386 break;
1387 }
1388
1389 BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
1390 entry->mem_ptr = vzalloc(memory_size + 1);
1391 entry->mem_size = memory_size;
1392 if (!entry->mem_ptr) {
1393 BT_ERR("Vzalloc %s failed", entry->mem_name);
1394 goto done;
1395 }
1396
1397 fw_dump_len += (strlen("========Start dump ") +
1398 strlen(entry->mem_name) +
1399 strlen("========\n") +
1400 (memory_size + 1) +
1401 strlen("\n========End dump========\n"));
1402
1403 dbg_ptr = entry->mem_ptr;
1404 end_ptr = dbg_ptr + memory_size;
1405
1406 doneflag = entry->done_flag;
1407 BT_INFO("Start %s output, please wait...",
1408 entry->mem_name);
1409
1410 do {
1411 stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1412 if (stat == RDWR_STATUS_FAILURE)
1413 goto done;
1414
1415 reg_start = card->reg->fw_dump_start;
1416 reg_end = card->reg->fw_dump_end;
1417 for (reg = reg_start; reg <= reg_end; reg++) {
1418 *dbg_ptr = sdio_readb(card->func, reg, &ret);
1419 if (ret) {
1420 BT_ERR("SDIO read err");
1421 goto done;
1422 }
1423 if (dbg_ptr < end_ptr)
1424 dbg_ptr++;
1425 else
1426 BT_ERR("Allocated buffer not enough");
1427 }
1428
1429 if (stat != RDWR_STATUS_DONE) {
1430 continue;
1431 } else {
1432 BT_INFO("%s done: size=0x%tx",
1433 entry->mem_name,
1434 dbg_ptr - entry->mem_ptr);
1435 break;
1436 }
1437 } while (1);
1438 }
1439
1440 BT_INFO("== btmrvl firmware dump end ==");
1441
1442done:
1443 sdio_release_host(card->func);
1444
1445 if (fw_dump_len == 0)
1446 return;
1447
1448 fw_dump_data = vzalloc(fw_dump_len+1);
1449 if (!fw_dump_data) {
1450 BT_ERR("Vzalloc fw_dump_data fail!");
1451 return;
1452 }
1453 fw_dump_ptr = fw_dump_data;
1454
1455 /* Dump all the memory data into single file, a userspace script will
1456 be used to split all the memory data to multiple files*/
1457 BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
1458 for (idx = 0; idx < dump_num; idx++) {
1459 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1460
1461 if (entry->mem_ptr) {
1462 strcpy(fw_dump_ptr, "========Start dump ");
1463 fw_dump_ptr += strlen("========Start dump ");
1464
1465 strcpy(fw_dump_ptr, entry->mem_name);
1466 fw_dump_ptr += strlen(entry->mem_name);
1467
1468 strcpy(fw_dump_ptr, "========\n");
1469 fw_dump_ptr += strlen("========\n");
1470
1471 memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
1472 fw_dump_ptr += entry->mem_size;
1473
1474 strcpy(fw_dump_ptr, "\n========End dump========\n");
1475 fw_dump_ptr += strlen("\n========End dump========\n");
1476
1477 vfree(mem_type_mapping_tbl[idx].mem_ptr);
1478 mem_type_mapping_tbl[idx].mem_ptr = NULL;
1479 }
1480 }
1481
1482 /* fw_dump_data will be free in device coredump release function
1483 after 5 min*/
Shengzhen Lid4902632015-08-19 03:12:19 -07001484 dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL);
Xinming Hudc759612014-11-24 02:40:53 -08001485 BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
1486}
1487
Bing Zhao789221e2009-06-02 14:29:36 -07001488static int btmrvl_sdio_probe(struct sdio_func *func,
Marcel Holtmanndcf47f32009-06-09 16:21:58 +02001489 const struct sdio_device_id *id)
Bing Zhao789221e2009-06-02 14:29:36 -07001490{
1491 int ret = 0;
1492 struct btmrvl_private *priv = NULL;
1493 struct btmrvl_sdio_card *card = NULL;
1494
Bing Zhao789221e2009-06-02 14:29:36 -07001495 BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
1496 id->vendor, id->device, id->class, func->num);
1497
Sachin Kamateb17ea32012-07-27 12:38:36 +05301498 card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
1499 if (!card)
1500 return -ENOMEM;
Bing Zhao789221e2009-06-02 14:29:36 -07001501
1502 card->func = func;
1503
Marcel Holtmanndcf47f32009-06-09 16:21:58 +02001504 if (id->driver_data) {
1505 struct btmrvl_sdio_device *data = (void *) id->driver_data;
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001506 card->helper = data->helper;
Marcel Holtmanndcf47f32009-06-09 16:21:58 +02001507 card->firmware = data->firmware;
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001508 card->reg = data->reg;
1509 card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
Bing Zhao4df82b52014-03-31 14:41:44 -07001510 card->support_pscan_win_report = data->support_pscan_win_report;
Xinming Hudc759612014-11-24 02:40:53 -08001511 card->supports_fw_dump = data->supports_fw_dump;
Marcel Holtmanndcf47f32009-06-09 16:21:58 +02001512 }
1513
Bing Zhao789221e2009-06-02 14:29:36 -07001514 if (btmrvl_sdio_register_dev(card) < 0) {
1515 BT_ERR("Failed to register BT device!");
Sachin Kamateb17ea32012-07-27 12:38:36 +05301516 return -ENODEV;
Bing Zhao789221e2009-06-02 14:29:36 -07001517 }
1518
1519 /* Disable the interrupts on the card */
1520 btmrvl_sdio_disable_host_int(card);
1521
1522 if (btmrvl_sdio_download_fw(card)) {
1523 BT_ERR("Downloading firmware failed!");
1524 ret = -ENODEV;
1525 goto unreg_dev;
1526 }
1527
Bing Zhao789221e2009-06-02 14:29:36 -07001528 btmrvl_sdio_enable_host_int(card);
1529
Xinming Hubb7f4f02016-04-26 06:57:27 -07001530 /* Device tree node parsing and platform specific configuration*/
1531 btmrvl_sdio_probe_of(&func->dev, card);
1532
Bing Zhao789221e2009-06-02 14:29:36 -07001533 priv = btmrvl_add_card(card);
1534 if (!priv) {
1535 BT_ERR("Initializing card failed!");
1536 ret = -ENODEV;
1537 goto disable_host_int;
1538 }
1539
1540 card->priv = priv;
1541
1542 /* Initialize the interface specific function pointers */
1543 priv->hw_host_to_card = btmrvl_sdio_host_to_card;
1544 priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
Amitkumar Karward1d10d72010-05-27 16:38:37 -07001545 priv->hw_process_int_status = btmrvl_sdio_process_int_status;
Xinming Hudc759612014-11-24 02:40:53 -08001546 priv->firmware_dump = btmrvl_sdio_dump_firmware;
Bing Zhao789221e2009-06-02 14:29:36 -07001547
Bing Zhao64061602010-03-03 14:37:36 -08001548 if (btmrvl_register_hdev(priv)) {
1549 BT_ERR("Register hdev failed!");
1550 ret = -ENODEV;
1551 goto disable_host_int;
1552 }
1553
Bing Zhao789221e2009-06-02 14:29:36 -07001554 return 0;
1555
1556disable_host_int:
1557 btmrvl_sdio_disable_host_int(card);
1558unreg_dev:
1559 btmrvl_sdio_unregister_dev(card);
Bing Zhao789221e2009-06-02 14:29:36 -07001560 return ret;
1561}
1562
1563static void btmrvl_sdio_remove(struct sdio_func *func)
1564{
1565 struct btmrvl_sdio_card *card;
1566
Bing Zhao789221e2009-06-02 14:29:36 -07001567 if (func) {
1568 card = sdio_get_drvdata(func);
1569 if (card) {
1570 /* Send SHUTDOWN command & disable interrupt
1571 * if user removes the module.
1572 */
1573 if (user_rmmod) {
1574 btmrvl_send_module_cfg_cmd(card->priv,
1575 MODULE_SHUTDOWN_REQ);
1576 btmrvl_sdio_disable_host_int(card);
1577 }
1578 BT_DBG("unregester dev");
Amitkumar Karwar7b4b8742015-01-01 00:13:41 -08001579 card->priv->surprise_removed = true;
Bing Zhao789221e2009-06-02 14:29:36 -07001580 btmrvl_sdio_unregister_dev(card);
1581 btmrvl_remove_card(card->priv);
Bing Zhao789221e2009-06-02 14:29:36 -07001582 }
1583 }
Bing Zhao789221e2009-06-02 14:29:36 -07001584}
1585
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001586static int btmrvl_sdio_suspend(struct device *dev)
1587{
1588 struct sdio_func *func = dev_to_sdio_func(dev);
1589 struct btmrvl_sdio_card *card;
1590 struct btmrvl_private *priv;
1591 mmc_pm_flag_t pm_flags;
1592 struct hci_dev *hcidev;
1593
1594 if (func) {
1595 pm_flags = sdio_get_host_pm_caps(func);
1596 BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func),
1597 pm_flags);
1598 if (!(pm_flags & MMC_PM_KEEP_POWER)) {
1599 BT_ERR("%s: cannot remain alive while suspended",
1600 sdio_func_id(func));
1601 return -ENOSYS;
1602 }
1603 card = sdio_get_drvdata(func);
1604 if (!card || !card->priv) {
1605 BT_ERR("card or priv structure is not valid");
1606 return 0;
1607 }
1608 } else {
1609 BT_ERR("sdio_func is not specified");
1610 return 0;
1611 }
1612
Xinming Hubb7f4f02016-04-26 06:57:27 -07001613 /* Enable platform specific wakeup interrupt */
1614 if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
1615 card->plt_wake_cfg->wake_by_bt = false;
1616 enable_irq(card->plt_wake_cfg->irq_bt);
1617 enable_irq_wake(card->plt_wake_cfg->irq_bt);
1618 }
1619
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001620 priv = card->priv;
Chin-Ran Lo8cf60cf2016-01-06 06:34:38 -08001621 priv->adapter->is_suspending = true;
Chin-Ran Lo5bf8a742014-07-14 21:05:37 -07001622 hcidev = priv->btmrvl_dev.hcidev;
1623 BT_DBG("%s: SDIO suspend", hcidev->name);
1624 hci_suspend_dev(hcidev);
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001625
1626 if (priv->adapter->hs_state != HS_ACTIVATED) {
1627 if (btmrvl_enable_hs(priv)) {
1628 BT_ERR("HS not actived, suspend failed!");
Amitkumar Karware7acf432016-07-15 16:20:52 +05301629 priv->adapter->is_suspending = false;
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001630 return -EBUSY;
1631 }
1632 }
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001633
Chin-Ran Lo8cf60cf2016-01-06 06:34:38 -08001634 priv->adapter->is_suspending = false;
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001635 priv->adapter->is_suspended = true;
1636
1637 /* We will keep the power when hs enabled successfully */
1638 if (priv->adapter->hs_state == HS_ACTIVATED) {
1639 BT_DBG("suspend with MMC_PM_KEEP_POWER");
1640 return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
1641 } else {
1642 BT_DBG("suspend without MMC_PM_KEEP_POWER");
1643 return 0;
1644 }
1645}
1646
1647static int btmrvl_sdio_resume(struct device *dev)
1648{
1649 struct sdio_func *func = dev_to_sdio_func(dev);
1650 struct btmrvl_sdio_card *card;
1651 struct btmrvl_private *priv;
1652 mmc_pm_flag_t pm_flags;
1653 struct hci_dev *hcidev;
1654
1655 if (func) {
1656 pm_flags = sdio_get_host_pm_caps(func);
1657 BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func),
1658 pm_flags);
1659 card = sdio_get_drvdata(func);
1660 if (!card || !card->priv) {
1661 BT_ERR("card or priv structure is not valid");
1662 return 0;
1663 }
1664 } else {
1665 BT_ERR("sdio_func is not specified");
1666 return 0;
1667 }
1668 priv = card->priv;
1669
1670 if (!priv->adapter->is_suspended) {
1671 BT_DBG("device already resumed");
1672 return 0;
1673 }
1674
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001675 priv->hw_wakeup_firmware(priv);
1676 priv->adapter->hs_state = HS_DEACTIVATED;
Chin-Ran Lo5bf8a742014-07-14 21:05:37 -07001677 hcidev = priv->btmrvl_dev.hcidev;
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001678 BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
Chin-Ran Lo5bf8a742014-07-14 21:05:37 -07001679 priv->adapter->is_suspended = false;
1680 BT_DBG("%s: SDIO resume", hcidev->name);
1681 hci_resume_dev(hcidev);
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001682
Xinming Hubb7f4f02016-04-26 06:57:27 -07001683 /* Disable platform specific wakeup interrupt */
1684 if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
1685 disable_irq_wake(card->plt_wake_cfg->irq_bt);
Jeffy Chen9af02d82017-01-23 12:18:51 +08001686 disable_irq(card->plt_wake_cfg->irq_bt);
1687 if (card->plt_wake_cfg->wake_by_bt)
1688 /* Undo our disable, since interrupt handler already
1689 * did this.
1690 */
1691 enable_irq(card->plt_wake_cfg->irq_bt);
Xinming Hubb7f4f02016-04-26 06:57:27 -07001692 }
1693
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001694 return 0;
1695}
1696
1697static const struct dev_pm_ops btmrvl_sdio_pm_ops = {
1698 .suspend = btmrvl_sdio_suspend,
1699 .resume = btmrvl_sdio_resume,
1700};
1701
Bing Zhao789221e2009-06-02 14:29:36 -07001702static struct sdio_driver bt_mrvl_sdio = {
1703 .name = "btmrvl_sdio",
1704 .id_table = btmrvl_sdio_ids,
1705 .probe = btmrvl_sdio_probe,
1706 .remove = btmrvl_sdio_remove,
Amitkumar Karwarba54a162012-04-25 11:43:54 -07001707 .drv = {
1708 .owner = THIS_MODULE,
1709 .pm = &btmrvl_sdio_pm_ops,
1710 }
Bing Zhao789221e2009-06-02 14:29:36 -07001711};
1712
Peter Huewe8e5b2302009-12-22 09:34:20 +01001713static int __init btmrvl_sdio_init_module(void)
Bing Zhao789221e2009-06-02 14:29:36 -07001714{
Bing Zhao789221e2009-06-02 14:29:36 -07001715 if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
1716 BT_ERR("SDIO Driver Registration Failed");
Bing Zhao789221e2009-06-02 14:29:36 -07001717 return -ENODEV;
1718 }
1719
1720 /* Clear the flag in case user removes the card. */
1721 user_rmmod = 0;
1722
Bing Zhao789221e2009-06-02 14:29:36 -07001723 return 0;
1724}
1725
Peter Huewe8e5b2302009-12-22 09:34:20 +01001726static void __exit btmrvl_sdio_exit_module(void)
Bing Zhao789221e2009-06-02 14:29:36 -07001727{
Bing Zhao789221e2009-06-02 14:29:36 -07001728 /* Set the flag as user is removing this module. */
1729 user_rmmod = 1;
1730
1731 sdio_unregister_driver(&bt_mrvl_sdio);
Bing Zhao789221e2009-06-02 14:29:36 -07001732}
1733
1734module_init(btmrvl_sdio_init_module);
1735module_exit(btmrvl_sdio_exit_module);
1736
1737MODULE_AUTHOR("Marvell International Ltd.");
Marcel Holtmann9666fb32009-06-09 21:45:04 +02001738MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
Bing Zhao789221e2009-06-02 14:29:36 -07001739MODULE_VERSION(VERSION);
1740MODULE_LICENSE("GPL v2");
Lubomir Rintel77189df2013-03-13 12:04:30 +01001741MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
1742MODULE_FIRMWARE("mrvl/sd8688.bin");
Kevin Gan9f72c1d2011-04-08 18:19:33 -07001743MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
Bing Zhao2ac654f2011-11-16 20:40:42 -08001744MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
Xinming Hu3907d552014-09-30 06:45:33 -04001745MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
Bing Zhao22f2efe2013-05-13 18:15:32 -07001746MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
Amitkumar Karwarf0ef6742015-09-21 03:06:42 -07001747MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");