xref: /OK3568_Linux_fs/kernel/drivers/bluetooth/btmrvl_sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /**
2*4882a593Smuzhiyun  * Marvell BT-over-SDIO driver: SDIO interface related functions.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2009, Marvell International Ltd.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This software file (the "File") is distributed by Marvell International
7*4882a593Smuzhiyun  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8*4882a593Smuzhiyun  * (the "License").  You may use, redistribute and/or modify this File in
9*4882a593Smuzhiyun  * accordance with the terms and conditions of the License, a copy of which
10*4882a593Smuzhiyun  * is available by writing to the Free Software Foundation, Inc.,
11*4882a593Smuzhiyun  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12*4882a593Smuzhiyun  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16*4882a593Smuzhiyun  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17*4882a593Smuzhiyun  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
18*4882a593Smuzhiyun  * this warranty disclaimer.
19*4882a593Smuzhiyun  **/
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include <linux/firmware.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/suspend.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <linux/mmc/sdio_ids.h>
26*4882a593Smuzhiyun #include <linux/mmc/sdio_func.h>
27*4882a593Smuzhiyun #include <linux/module.h>
28*4882a593Smuzhiyun #include <linux/devcoredump.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <net/bluetooth/bluetooth.h>
31*4882a593Smuzhiyun #include <net/bluetooth/hci_core.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include "btmrvl_drv.h"
34*4882a593Smuzhiyun #include "btmrvl_sdio.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define VERSION "1.0"
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static struct memory_type_mapping mem_type_mapping_tbl[] = {
39*4882a593Smuzhiyun 	{"ITCM", NULL, 0, 0xF0},
40*4882a593Smuzhiyun 	{"DTCM", NULL, 0, 0xF1},
41*4882a593Smuzhiyun 	{"SQRAM", NULL, 0, 0xF2},
42*4882a593Smuzhiyun 	{"APU", NULL, 0, 0xF3},
43*4882a593Smuzhiyun 	{"CIU", NULL, 0, 0xF4},
44*4882a593Smuzhiyun 	{"ICU", NULL, 0, 0xF5},
45*4882a593Smuzhiyun 	{"MAC", NULL, 0, 0xF6},
46*4882a593Smuzhiyun 	{"EXT7", NULL, 0, 0xF7},
47*4882a593Smuzhiyun 	{"EXT8", NULL, 0, 0xF8},
48*4882a593Smuzhiyun 	{"EXT9", NULL, 0, 0xF9},
49*4882a593Smuzhiyun 	{"EXT10", NULL, 0, 0xFA},
50*4882a593Smuzhiyun 	{"EXT11", NULL, 0, 0xFB},
51*4882a593Smuzhiyun 	{"EXT12", NULL, 0, 0xFC},
52*4882a593Smuzhiyun 	{"EXT13", NULL, 0, 0xFD},
53*4882a593Smuzhiyun 	{"EXTLAST", NULL, 0, 0xFE},
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static const struct of_device_id btmrvl_sdio_of_match_table[] = {
57*4882a593Smuzhiyun 	{ .compatible = "marvell,sd8897-bt" },
58*4882a593Smuzhiyun 	{ .compatible = "marvell,sd8997-bt" },
59*4882a593Smuzhiyun 	{ }
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
btmrvl_wake_irq_bt(int irq,void * priv)62*4882a593Smuzhiyun static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv;
65*4882a593Smuzhiyun 	struct device *dev = &card->func->dev;
66*4882a593Smuzhiyun 	struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	dev_info(dev, "wake by bt\n");
69*4882a593Smuzhiyun 	cfg->wake_by_bt = true;
70*4882a593Smuzhiyun 	disable_irq_nosync(irq);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	pm_wakeup_event(dev, 0);
73*4882a593Smuzhiyun 	pm_system_wakeup();
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	return IRQ_HANDLED;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* This function parses device tree node using mmc subnode devicetree API.
79*4882a593Smuzhiyun  * The device node is saved in card->plt_of_node.
80*4882a593Smuzhiyun  * If the device tree node exists and includes interrupts attributes, this
81*4882a593Smuzhiyun  * function will request platform specific wakeup interrupt.
82*4882a593Smuzhiyun  */
btmrvl_sdio_probe_of(struct device * dev,struct btmrvl_sdio_card * card)83*4882a593Smuzhiyun static int btmrvl_sdio_probe_of(struct device *dev,
84*4882a593Smuzhiyun 				struct btmrvl_sdio_card *card)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct btmrvl_plt_wake_cfg *cfg;
87*4882a593Smuzhiyun 	int ret;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	if (!dev->of_node ||
90*4882a593Smuzhiyun 	    !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
91*4882a593Smuzhiyun 		dev_info(dev, "sdio device tree data not available\n");
92*4882a593Smuzhiyun 		return -1;
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	card->plt_of_node = dev->of_node;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
98*4882a593Smuzhiyun 					  GFP_KERNEL);
99*4882a593Smuzhiyun 	cfg = card->plt_wake_cfg;
100*4882a593Smuzhiyun 	if (cfg && card->plt_of_node) {
101*4882a593Smuzhiyun 		cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
102*4882a593Smuzhiyun 		if (!cfg->irq_bt) {
103*4882a593Smuzhiyun 			dev_err(dev, "fail to parse irq_bt from device tree\n");
104*4882a593Smuzhiyun 			cfg->irq_bt = -1;
105*4882a593Smuzhiyun 		} else {
106*4882a593Smuzhiyun 			ret = devm_request_irq(dev, cfg->irq_bt,
107*4882a593Smuzhiyun 					       btmrvl_wake_irq_bt,
108*4882a593Smuzhiyun 					       0, "bt_wake", card);
109*4882a593Smuzhiyun 			if (ret) {
110*4882a593Smuzhiyun 				dev_err(dev,
111*4882a593Smuzhiyun 					"Failed to request irq_bt %d (%d)\n",
112*4882a593Smuzhiyun 					cfg->irq_bt, ret);
113*4882a593Smuzhiyun 			}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 			/* Configure wakeup (enabled by default) */
116*4882a593Smuzhiyun 			device_init_wakeup(dev, true);
117*4882a593Smuzhiyun 			disable_irq(cfg->irq_bt);
118*4882a593Smuzhiyun 		}
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return 0;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /* The btmrvl_sdio_remove() callback function is called
125*4882a593Smuzhiyun  * when user removes this module from kernel space or ejects
126*4882a593Smuzhiyun  * the card from the slot. The driver handles these 2 cases
127*4882a593Smuzhiyun  * differently.
128*4882a593Smuzhiyun  * If the user is removing the module, a MODULE_SHUTDOWN_REQ
129*4882a593Smuzhiyun  * command is sent to firmware and interrupt will be disabled.
130*4882a593Smuzhiyun  * If the card is removed, there is no need to send command
131*4882a593Smuzhiyun  * or disable interrupt.
132*4882a593Smuzhiyun  *
133*4882a593Smuzhiyun  * The variable 'user_rmmod' is used to distinguish these two
134*4882a593Smuzhiyun  * scenarios. This flag is initialized as FALSE in case the card
135*4882a593Smuzhiyun  * is removed, and will be set to TRUE for module removal when
136*4882a593Smuzhiyun  * module_exit function is called.
137*4882a593Smuzhiyun  */
138*4882a593Smuzhiyun static u8 user_rmmod;
139*4882a593Smuzhiyun static u8 sdio_ireg;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
142*4882a593Smuzhiyun 	.cfg = 0x03,
143*4882a593Smuzhiyun 	.host_int_mask = 0x04,
144*4882a593Smuzhiyun 	.host_intstatus = 0x05,
145*4882a593Smuzhiyun 	.card_status = 0x20,
146*4882a593Smuzhiyun 	.sq_read_base_addr_a0 = 0x10,
147*4882a593Smuzhiyun 	.sq_read_base_addr_a1 = 0x11,
148*4882a593Smuzhiyun 	.card_fw_status0 = 0x40,
149*4882a593Smuzhiyun 	.card_fw_status1 = 0x41,
150*4882a593Smuzhiyun 	.card_rx_len = 0x42,
151*4882a593Smuzhiyun 	.card_rx_unit = 0x43,
152*4882a593Smuzhiyun 	.io_port_0 = 0x00,
153*4882a593Smuzhiyun 	.io_port_1 = 0x01,
154*4882a593Smuzhiyun 	.io_port_2 = 0x02,
155*4882a593Smuzhiyun 	.int_read_to_clear = false,
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
158*4882a593Smuzhiyun 	.cfg = 0x00,
159*4882a593Smuzhiyun 	.host_int_mask = 0x02,
160*4882a593Smuzhiyun 	.host_intstatus = 0x03,
161*4882a593Smuzhiyun 	.card_status = 0x30,
162*4882a593Smuzhiyun 	.sq_read_base_addr_a0 = 0x40,
163*4882a593Smuzhiyun 	.sq_read_base_addr_a1 = 0x41,
164*4882a593Smuzhiyun 	.card_revision = 0x5c,
165*4882a593Smuzhiyun 	.card_fw_status0 = 0x60,
166*4882a593Smuzhiyun 	.card_fw_status1 = 0x61,
167*4882a593Smuzhiyun 	.card_rx_len = 0x62,
168*4882a593Smuzhiyun 	.card_rx_unit = 0x63,
169*4882a593Smuzhiyun 	.io_port_0 = 0x78,
170*4882a593Smuzhiyun 	.io_port_1 = 0x79,
171*4882a593Smuzhiyun 	.io_port_2 = 0x7a,
172*4882a593Smuzhiyun 	.int_read_to_clear = false,
173*4882a593Smuzhiyun };
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun static const struct btmrvl_sdio_card_reg btmrvl_reg_8887 = {
176*4882a593Smuzhiyun 	.cfg = 0x00,
177*4882a593Smuzhiyun 	.host_int_mask = 0x08,
178*4882a593Smuzhiyun 	.host_intstatus = 0x0C,
179*4882a593Smuzhiyun 	.card_status = 0x5C,
180*4882a593Smuzhiyun 	.sq_read_base_addr_a0 = 0x6C,
181*4882a593Smuzhiyun 	.sq_read_base_addr_a1 = 0x6D,
182*4882a593Smuzhiyun 	.card_revision = 0xC8,
183*4882a593Smuzhiyun 	.card_fw_status0 = 0x88,
184*4882a593Smuzhiyun 	.card_fw_status1 = 0x89,
185*4882a593Smuzhiyun 	.card_rx_len = 0x8A,
186*4882a593Smuzhiyun 	.card_rx_unit = 0x8B,
187*4882a593Smuzhiyun 	.io_port_0 = 0xE4,
188*4882a593Smuzhiyun 	.io_port_1 = 0xE5,
189*4882a593Smuzhiyun 	.io_port_2 = 0xE6,
190*4882a593Smuzhiyun 	.int_read_to_clear = true,
191*4882a593Smuzhiyun 	.host_int_rsr = 0x04,
192*4882a593Smuzhiyun 	.card_misc_cfg = 0xD8,
193*4882a593Smuzhiyun };
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
196*4882a593Smuzhiyun 	.cfg = 0x00,
197*4882a593Smuzhiyun 	.host_int_mask = 0x02,
198*4882a593Smuzhiyun 	.host_intstatus = 0x03,
199*4882a593Smuzhiyun 	.card_status = 0x50,
200*4882a593Smuzhiyun 	.sq_read_base_addr_a0 = 0x60,
201*4882a593Smuzhiyun 	.sq_read_base_addr_a1 = 0x61,
202*4882a593Smuzhiyun 	.card_revision = 0xbc,
203*4882a593Smuzhiyun 	.card_fw_status0 = 0xc0,
204*4882a593Smuzhiyun 	.card_fw_status1 = 0xc1,
205*4882a593Smuzhiyun 	.card_rx_len = 0xc2,
206*4882a593Smuzhiyun 	.card_rx_unit = 0xc3,
207*4882a593Smuzhiyun 	.io_port_0 = 0xd8,
208*4882a593Smuzhiyun 	.io_port_1 = 0xd9,
209*4882a593Smuzhiyun 	.io_port_2 = 0xda,
210*4882a593Smuzhiyun 	.int_read_to_clear = true,
211*4882a593Smuzhiyun 	.host_int_rsr = 0x01,
212*4882a593Smuzhiyun 	.card_misc_cfg = 0xcc,
213*4882a593Smuzhiyun 	.fw_dump_ctrl = 0xe2,
214*4882a593Smuzhiyun 	.fw_dump_start = 0xe3,
215*4882a593Smuzhiyun 	.fw_dump_end = 0xea,
216*4882a593Smuzhiyun };
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun static const struct btmrvl_sdio_card_reg btmrvl_reg_89xx = {
219*4882a593Smuzhiyun 	.cfg = 0x00,
220*4882a593Smuzhiyun 	.host_int_mask = 0x08,
221*4882a593Smuzhiyun 	.host_intstatus = 0x0c,
222*4882a593Smuzhiyun 	.card_status = 0x5c,
223*4882a593Smuzhiyun 	.sq_read_base_addr_a0 = 0xf8,
224*4882a593Smuzhiyun 	.sq_read_base_addr_a1 = 0xf9,
225*4882a593Smuzhiyun 	.card_revision = 0xc8,
226*4882a593Smuzhiyun 	.card_fw_status0 = 0xe8,
227*4882a593Smuzhiyun 	.card_fw_status1 = 0xe9,
228*4882a593Smuzhiyun 	.card_rx_len = 0xea,
229*4882a593Smuzhiyun 	.card_rx_unit = 0xeb,
230*4882a593Smuzhiyun 	.io_port_0 = 0xe4,
231*4882a593Smuzhiyun 	.io_port_1 = 0xe5,
232*4882a593Smuzhiyun 	.io_port_2 = 0xe6,
233*4882a593Smuzhiyun 	.int_read_to_clear = true,
234*4882a593Smuzhiyun 	.host_int_rsr = 0x04,
235*4882a593Smuzhiyun 	.card_misc_cfg = 0xd8,
236*4882a593Smuzhiyun 	.fw_dump_ctrl = 0xf0,
237*4882a593Smuzhiyun 	.fw_dump_start = 0xf1,
238*4882a593Smuzhiyun 	.fw_dump_end = 0xf8,
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
242*4882a593Smuzhiyun 	.helper		= "mrvl/sd8688_helper.bin",
243*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8688.bin",
244*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_8688,
245*4882a593Smuzhiyun 	.support_pscan_win_report = false,
246*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 64,
247*4882a593Smuzhiyun 	.supports_fw_dump = false,
248*4882a593Smuzhiyun };
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
251*4882a593Smuzhiyun 	.helper		= NULL,
252*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8787_uapsta.bin",
253*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_87xx,
254*4882a593Smuzhiyun 	.support_pscan_win_report = false,
255*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 256,
256*4882a593Smuzhiyun 	.supports_fw_dump = false,
257*4882a593Smuzhiyun };
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
260*4882a593Smuzhiyun 	.helper		= NULL,
261*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8797_uapsta.bin",
262*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_87xx,
263*4882a593Smuzhiyun 	.support_pscan_win_report = false,
264*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 256,
265*4882a593Smuzhiyun 	.supports_fw_dump = false,
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
269*4882a593Smuzhiyun 	.helper		= NULL,
270*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8887_uapsta.bin",
271*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_8887,
272*4882a593Smuzhiyun 	.support_pscan_win_report = true,
273*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 256,
274*4882a593Smuzhiyun 	.supports_fw_dump = false,
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
278*4882a593Smuzhiyun 	.helper		= NULL,
279*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8897_uapsta.bin",
280*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_8897,
281*4882a593Smuzhiyun 	.support_pscan_win_report = true,
282*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 256,
283*4882a593Smuzhiyun 	.supports_fw_dump = true,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
287*4882a593Smuzhiyun 	.helper         = NULL,
288*4882a593Smuzhiyun 	.firmware       = "mrvl/sdsd8977_combo_v2.bin",
289*4882a593Smuzhiyun 	.reg            = &btmrvl_reg_89xx,
290*4882a593Smuzhiyun 	.support_pscan_win_report = true,
291*4882a593Smuzhiyun 	.sd_blksz_fw_dl = 256,
292*4882a593Smuzhiyun 	.supports_fw_dump = true,
293*4882a593Smuzhiyun };
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = {
296*4882a593Smuzhiyun 	.helper		= NULL,
297*4882a593Smuzhiyun 	.firmware	= "mrvl/sd8987_uapsta.bin",
298*4882a593Smuzhiyun 	.reg		= &btmrvl_reg_89xx,
299*4882a593Smuzhiyun 	.support_pscan_win_report = true,
300*4882a593Smuzhiyun 	.sd_blksz_fw_dl	= 256,
301*4882a593Smuzhiyun 	.supports_fw_dump = true,
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
305*4882a593Smuzhiyun 	.helper         = NULL,
306*4882a593Smuzhiyun 	.firmware       = "mrvl/sdsd8997_combo_v4.bin",
307*4882a593Smuzhiyun 	.reg            = &btmrvl_reg_89xx,
308*4882a593Smuzhiyun 	.support_pscan_win_report = true,
309*4882a593Smuzhiyun 	.sd_blksz_fw_dl = 256,
310*4882a593Smuzhiyun 	.supports_fw_dump = true,
311*4882a593Smuzhiyun };
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun static const struct sdio_device_id btmrvl_sdio_ids[] = {
314*4882a593Smuzhiyun 	/* Marvell SD8688 Bluetooth device */
315*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8688_BT),
316*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
317*4882a593Smuzhiyun 	/* Marvell SD8787 Bluetooth device */
318*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787_BT),
319*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
320*4882a593Smuzhiyun 	/* Marvell SD8787 Bluetooth AMP device */
321*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787_BT_AMP),
322*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
323*4882a593Smuzhiyun 	/* Marvell SD8797 Bluetooth device */
324*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_BT),
325*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
326*4882a593Smuzhiyun 	/* Marvell SD8887 Bluetooth device */
327*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887_BT),
328*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
329*4882a593Smuzhiyun 	/* Marvell SD8897 Bluetooth device */
330*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897_BT),
331*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
332*4882a593Smuzhiyun 	/* Marvell SD8977 Bluetooth device */
333*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8977_BT),
334*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8977 },
335*4882a593Smuzhiyun 	/* Marvell SD8987 Bluetooth device */
336*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8987_BT),
337*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8987 },
338*4882a593Smuzhiyun 	/* Marvell SD8997 Bluetooth device */
339*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997_BT),
340*4882a593Smuzhiyun 			.driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	{ }	/* Terminating entry */
343*4882a593Smuzhiyun };
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
346*4882a593Smuzhiyun 
btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card * card)347*4882a593Smuzhiyun static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	u8 reg;
350*4882a593Smuzhiyun 	int ret;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
353*4882a593Smuzhiyun 	if (!ret)
354*4882a593Smuzhiyun 		card->rx_unit = reg;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	return ret;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card * card,u16 * dat)359*4882a593Smuzhiyun static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun 	u8 fws0, fws1;
362*4882a593Smuzhiyun 	int ret;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	*dat = 0;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
367*4882a593Smuzhiyun 	if (ret)
368*4882a593Smuzhiyun 		return -EIO;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
371*4882a593Smuzhiyun 	if (ret)
372*4882a593Smuzhiyun 		return -EIO;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	*dat = (((u16) fws1) << 8) | fws0;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card * card,u16 * dat)379*4882a593Smuzhiyun static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	u8 reg;
382*4882a593Smuzhiyun 	int ret;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
385*4882a593Smuzhiyun 	if (!ret)
386*4882a593Smuzhiyun 		*dat = (u16) reg << card->rx_unit;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	return ret;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card * card,u8 mask)391*4882a593Smuzhiyun static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
392*4882a593Smuzhiyun 								u8 mask)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	int ret;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
397*4882a593Smuzhiyun 	if (ret) {
398*4882a593Smuzhiyun 		BT_ERR("Unable to enable the host interrupt!");
399*4882a593Smuzhiyun 		ret = -EIO;
400*4882a593Smuzhiyun 	}
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	return ret;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card * card,u8 mask)405*4882a593Smuzhiyun static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
406*4882a593Smuzhiyun 								u8 mask)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	u8 host_int_mask;
409*4882a593Smuzhiyun 	int ret;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
412*4882a593Smuzhiyun 	if (ret)
413*4882a593Smuzhiyun 		return -EIO;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	host_int_mask &= ~mask;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
418*4882a593Smuzhiyun 	if (ret < 0) {
419*4882a593Smuzhiyun 		BT_ERR("Unable to disable the host interrupt!");
420*4882a593Smuzhiyun 		return -EIO;
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card * card,u8 bits)426*4882a593Smuzhiyun static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun 	unsigned int tries;
429*4882a593Smuzhiyun 	u8 status;
430*4882a593Smuzhiyun 	int ret;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
433*4882a593Smuzhiyun 		status = sdio_readb(card->func, card->reg->card_status,	&ret);
434*4882a593Smuzhiyun 		if (ret)
435*4882a593Smuzhiyun 			goto failed;
436*4882a593Smuzhiyun 		if ((status & bits) == bits)
437*4882a593Smuzhiyun 			return ret;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 		udelay(1);
440*4882a593Smuzhiyun 	}
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	ret = -ETIMEDOUT;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun failed:
445*4882a593Smuzhiyun 	BT_ERR("FAILED! ret=%d", ret);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	return ret;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card * card,int pollnum)450*4882a593Smuzhiyun static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
451*4882a593Smuzhiyun 								int pollnum)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun 	u16 firmwarestat;
454*4882a593Smuzhiyun 	int tries, ret;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	 /* Wait for firmware to become ready */
457*4882a593Smuzhiyun 	for (tries = 0; tries < pollnum; tries++) {
458*4882a593Smuzhiyun 		sdio_claim_host(card->func);
459*4882a593Smuzhiyun 		ret = btmrvl_sdio_read_fw_status(card, &firmwarestat);
460*4882a593Smuzhiyun 		sdio_release_host(card->func);
461*4882a593Smuzhiyun 		if (ret < 0)
462*4882a593Smuzhiyun 			continue;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 		if (firmwarestat == FIRMWARE_READY)
465*4882a593Smuzhiyun 			return 0;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 		msleep(100);
468*4882a593Smuzhiyun 	}
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	return -ETIMEDOUT;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
btmrvl_sdio_download_helper(struct btmrvl_sdio_card * card)473*4882a593Smuzhiyun static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	const struct firmware *fw_helper = NULL;
476*4882a593Smuzhiyun 	const u8 *helper = NULL;
477*4882a593Smuzhiyun 	int ret;
478*4882a593Smuzhiyun 	void *tmphlprbuf = NULL;
479*4882a593Smuzhiyun 	int tmphlprbufsz, hlprblknow, helperlen;
480*4882a593Smuzhiyun 	u8 *helperbuf;
481*4882a593Smuzhiyun 	u32 tx_len;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	ret = request_firmware(&fw_helper, card->helper,
484*4882a593Smuzhiyun 						&card->func->dev);
485*4882a593Smuzhiyun 	if ((ret < 0) || !fw_helper) {
486*4882a593Smuzhiyun 		BT_ERR("request_firmware(helper) failed, error code = %d",
487*4882a593Smuzhiyun 									ret);
488*4882a593Smuzhiyun 		ret = -ENOENT;
489*4882a593Smuzhiyun 		goto done;
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	helper = fw_helper->data;
493*4882a593Smuzhiyun 	helperlen = fw_helper->size;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	BT_DBG("Downloading helper image (%d bytes), block size %d bytes",
496*4882a593Smuzhiyun 						helperlen, SDIO_BLOCK_SIZE);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
501*4882a593Smuzhiyun 	if (!tmphlprbuf) {
502*4882a593Smuzhiyun 		BT_ERR("Unable to allocate buffer for helper."
503*4882a593Smuzhiyun 			" Terminating download");
504*4882a593Smuzhiyun 		ret = -ENOMEM;
505*4882a593Smuzhiyun 		goto done;
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	/* Perform helper data transfer */
511*4882a593Smuzhiyun 	tx_len = (FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE)
512*4882a593Smuzhiyun 			- SDIO_HEADER_LEN;
513*4882a593Smuzhiyun 	hlprblknow = 0;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	do {
516*4882a593Smuzhiyun 		ret = btmrvl_sdio_poll_card_status(card,
517*4882a593Smuzhiyun 					    CARD_IO_READY | DN_LD_CARD_RDY);
518*4882a593Smuzhiyun 		if (ret < 0) {
519*4882a593Smuzhiyun 			BT_ERR("Helper download poll status timeout @ %d",
520*4882a593Smuzhiyun 				hlprblknow);
521*4882a593Smuzhiyun 			goto done;
522*4882a593Smuzhiyun 		}
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 		/* Check if there is more data? */
525*4882a593Smuzhiyun 		if (hlprblknow >= helperlen)
526*4882a593Smuzhiyun 			break;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 		if (helperlen - hlprblknow < tx_len)
529*4882a593Smuzhiyun 			tx_len = helperlen - hlprblknow;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 		/* Little-endian */
532*4882a593Smuzhiyun 		helperbuf[0] = ((tx_len & 0x000000ff) >> 0);
533*4882a593Smuzhiyun 		helperbuf[1] = ((tx_len & 0x0000ff00) >> 8);
534*4882a593Smuzhiyun 		helperbuf[2] = ((tx_len & 0x00ff0000) >> 16);
535*4882a593Smuzhiyun 		helperbuf[3] = ((tx_len & 0xff000000) >> 24);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		memcpy(&helperbuf[SDIO_HEADER_LEN], &helper[hlprblknow],
538*4882a593Smuzhiyun 				tx_len);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 		/* Now send the data */
541*4882a593Smuzhiyun 		ret = sdio_writesb(card->func, card->ioport, helperbuf,
542*4882a593Smuzhiyun 				FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE);
543*4882a593Smuzhiyun 		if (ret < 0) {
544*4882a593Smuzhiyun 			BT_ERR("IO error during helper download @ %d",
545*4882a593Smuzhiyun 				hlprblknow);
546*4882a593Smuzhiyun 			goto done;
547*4882a593Smuzhiyun 		}
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 		hlprblknow += tx_len;
550*4882a593Smuzhiyun 	} while (true);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	BT_DBG("Transferring helper image EOF block");
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	memset(helperbuf, 0x0, SDIO_BLOCK_SIZE);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	ret = sdio_writesb(card->func, card->ioport, helperbuf,
557*4882a593Smuzhiyun 							SDIO_BLOCK_SIZE);
558*4882a593Smuzhiyun 	if (ret < 0) {
559*4882a593Smuzhiyun 		BT_ERR("IO error in writing helper image EOF block");
560*4882a593Smuzhiyun 		goto done;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	ret = 0;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun done:
566*4882a593Smuzhiyun 	kfree(tmphlprbuf);
567*4882a593Smuzhiyun 	release_firmware(fw_helper);
568*4882a593Smuzhiyun 	return ret;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun 
btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card * card)571*4882a593Smuzhiyun static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun 	const struct firmware *fw_firmware = NULL;
574*4882a593Smuzhiyun 	const u8 *firmware = NULL;
575*4882a593Smuzhiyun 	int firmwarelen, tmpfwbufsz, ret;
576*4882a593Smuzhiyun 	unsigned int tries, offset;
577*4882a593Smuzhiyun 	u8 base0, base1;
578*4882a593Smuzhiyun 	void *tmpfwbuf = NULL;
579*4882a593Smuzhiyun 	u8 *fwbuf;
580*4882a593Smuzhiyun 	u16 len, blksz_dl = card->sd_blksz_fw_dl;
581*4882a593Smuzhiyun 	int txlen = 0, tx_blocks = 0, count = 0;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	ret = request_firmware(&fw_firmware, card->firmware,
584*4882a593Smuzhiyun 							&card->func->dev);
585*4882a593Smuzhiyun 	if ((ret < 0) || !fw_firmware) {
586*4882a593Smuzhiyun 		BT_ERR("request_firmware(firmware) failed, error code = %d",
587*4882a593Smuzhiyun 									ret);
588*4882a593Smuzhiyun 		ret = -ENOENT;
589*4882a593Smuzhiyun 		goto done;
590*4882a593Smuzhiyun 	}
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	firmware = fw_firmware->data;
593*4882a593Smuzhiyun 	firmwarelen = fw_firmware->size;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
598*4882a593Smuzhiyun 	tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
599*4882a593Smuzhiyun 	if (!tmpfwbuf) {
600*4882a593Smuzhiyun 		BT_ERR("Unable to allocate buffer for firmware."
601*4882a593Smuzhiyun 		       " Terminating download");
602*4882a593Smuzhiyun 		ret = -ENOMEM;
603*4882a593Smuzhiyun 		goto done;
604*4882a593Smuzhiyun 	}
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	/* Ensure aligned firmware buffer */
607*4882a593Smuzhiyun 	fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	/* Perform firmware data transfer */
610*4882a593Smuzhiyun 	offset = 0;
611*4882a593Smuzhiyun 	do {
612*4882a593Smuzhiyun 		ret = btmrvl_sdio_poll_card_status(card,
613*4882a593Smuzhiyun 					CARD_IO_READY | DN_LD_CARD_RDY);
614*4882a593Smuzhiyun 		if (ret < 0) {
615*4882a593Smuzhiyun 			BT_ERR("FW download with helper poll status"
616*4882a593Smuzhiyun 						" timeout @ %d", offset);
617*4882a593Smuzhiyun 			goto done;
618*4882a593Smuzhiyun 		}
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 		/* Check if there is more data ? */
621*4882a593Smuzhiyun 		if (offset >= firmwarelen)
622*4882a593Smuzhiyun 			break;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
625*4882a593Smuzhiyun 			base0 = sdio_readb(card->func,
626*4882a593Smuzhiyun 					card->reg->sq_read_base_addr_a0, &ret);
627*4882a593Smuzhiyun 			if (ret) {
628*4882a593Smuzhiyun 				BT_ERR("BASE0 register read failed:"
629*4882a593Smuzhiyun 					" base0 = 0x%04X(%d)."
630*4882a593Smuzhiyun 					" Terminating download",
631*4882a593Smuzhiyun 					base0, base0);
632*4882a593Smuzhiyun 				ret = -EIO;
633*4882a593Smuzhiyun 				goto done;
634*4882a593Smuzhiyun 			}
635*4882a593Smuzhiyun 			base1 = sdio_readb(card->func,
636*4882a593Smuzhiyun 					card->reg->sq_read_base_addr_a1, &ret);
637*4882a593Smuzhiyun 			if (ret) {
638*4882a593Smuzhiyun 				BT_ERR("BASE1 register read failed:"
639*4882a593Smuzhiyun 					" base1 = 0x%04X(%d)."
640*4882a593Smuzhiyun 					" Terminating download",
641*4882a593Smuzhiyun 					base1, base1);
642*4882a593Smuzhiyun 				ret = -EIO;
643*4882a593Smuzhiyun 				goto done;
644*4882a593Smuzhiyun 			}
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 			len = (((u16) base1) << 8) | base0;
647*4882a593Smuzhiyun 			if (len)
648*4882a593Smuzhiyun 				break;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 			udelay(10);
651*4882a593Smuzhiyun 		}
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 		if (!len)
654*4882a593Smuzhiyun 			break;
655*4882a593Smuzhiyun 		else if (len > BTM_UPLD_SIZE) {
656*4882a593Smuzhiyun 			BT_ERR("FW download failure @%d, invalid length %d",
657*4882a593Smuzhiyun 								offset, len);
658*4882a593Smuzhiyun 			ret = -EINVAL;
659*4882a593Smuzhiyun 			goto done;
660*4882a593Smuzhiyun 		}
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 		txlen = len;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 		if (len & BIT(0)) {
665*4882a593Smuzhiyun 			count++;
666*4882a593Smuzhiyun 			if (count > MAX_WRITE_IOMEM_RETRY) {
667*4882a593Smuzhiyun 				BT_ERR("FW download failure @%d, "
668*4882a593Smuzhiyun 					"over max retry count", offset);
669*4882a593Smuzhiyun 				ret = -EIO;
670*4882a593Smuzhiyun 				goto done;
671*4882a593Smuzhiyun 			}
672*4882a593Smuzhiyun 			BT_ERR("FW CRC error indicated by the helper: "
673*4882a593Smuzhiyun 				"len = 0x%04X, txlen = %d", len, txlen);
674*4882a593Smuzhiyun 			len &= ~BIT(0);
675*4882a593Smuzhiyun 			/* Set txlen to 0 so as to resend from same offset */
676*4882a593Smuzhiyun 			txlen = 0;
677*4882a593Smuzhiyun 		} else {
678*4882a593Smuzhiyun 			count = 0;
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 			/* Last block ? */
681*4882a593Smuzhiyun 			if (firmwarelen - offset < txlen)
682*4882a593Smuzhiyun 				txlen = firmwarelen - offset;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 			tx_blocks = DIV_ROUND_UP(txlen, blksz_dl);
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 			memcpy(fwbuf, &firmware[offset], txlen);
687*4882a593Smuzhiyun 		}
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 		ret = sdio_writesb(card->func, card->ioport, fwbuf,
690*4882a593Smuzhiyun 						tx_blocks * blksz_dl);
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 		if (ret < 0) {
693*4882a593Smuzhiyun 			BT_ERR("FW download, writesb(%d) failed @%d",
694*4882a593Smuzhiyun 							count, offset);
695*4882a593Smuzhiyun 			sdio_writeb(card->func, HOST_CMD53_FIN,
696*4882a593Smuzhiyun 						card->reg->cfg, &ret);
697*4882a593Smuzhiyun 			if (ret)
698*4882a593Smuzhiyun 				BT_ERR("writeb failed (CFG)");
699*4882a593Smuzhiyun 		}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 		offset += txlen;
702*4882a593Smuzhiyun 	} while (true);
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	BT_INFO("FW download over, size %d bytes", offset);
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	ret = 0;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun done:
709*4882a593Smuzhiyun 	kfree(tmpfwbuf);
710*4882a593Smuzhiyun 	release_firmware(fw_firmware);
711*4882a593Smuzhiyun 	return ret;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
btmrvl_sdio_card_to_host(struct btmrvl_private * priv)714*4882a593Smuzhiyun static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	u16 buf_len = 0;
717*4882a593Smuzhiyun 	int ret, num_blocks, blksz;
718*4882a593Smuzhiyun 	struct sk_buff *skb = NULL;
719*4882a593Smuzhiyun 	u32 type;
720*4882a593Smuzhiyun 	u8 *payload;
721*4882a593Smuzhiyun 	struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
722*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	if (!card || !card->func) {
725*4882a593Smuzhiyun 		BT_ERR("card or function is NULL!");
726*4882a593Smuzhiyun 		ret = -EINVAL;
727*4882a593Smuzhiyun 		goto exit;
728*4882a593Smuzhiyun 	}
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	/* Read the length of data to be transferred */
731*4882a593Smuzhiyun 	ret = btmrvl_sdio_read_rx_len(card, &buf_len);
732*4882a593Smuzhiyun 	if (ret < 0) {
733*4882a593Smuzhiyun 		BT_ERR("read rx_len failed");
734*4882a593Smuzhiyun 		ret = -EIO;
735*4882a593Smuzhiyun 		goto exit;
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	blksz = SDIO_BLOCK_SIZE;
739*4882a593Smuzhiyun 	num_blocks = DIV_ROUND_UP(buf_len, blksz);
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (buf_len <= SDIO_HEADER_LEN
742*4882a593Smuzhiyun 	    || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
743*4882a593Smuzhiyun 		BT_ERR("invalid packet length: %d", buf_len);
744*4882a593Smuzhiyun 		ret = -EINVAL;
745*4882a593Smuzhiyun 		goto exit;
746*4882a593Smuzhiyun 	}
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	/* Allocate buffer */
749*4882a593Smuzhiyun 	skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_KERNEL);
750*4882a593Smuzhiyun 	if (!skb) {
751*4882a593Smuzhiyun 		BT_ERR("No free skb");
752*4882a593Smuzhiyun 		ret = -ENOMEM;
753*4882a593Smuzhiyun 		goto exit;
754*4882a593Smuzhiyun 	}
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	if ((unsigned long) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
757*4882a593Smuzhiyun 		skb_put(skb, (unsigned long) skb->data &
758*4882a593Smuzhiyun 					(BTSDIO_DMA_ALIGN - 1));
759*4882a593Smuzhiyun 		skb_pull(skb, (unsigned long) skb->data &
760*4882a593Smuzhiyun 					(BTSDIO_DMA_ALIGN - 1));
761*4882a593Smuzhiyun 	}
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	payload = skb->data;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	ret = sdio_readsb(card->func, payload, card->ioport,
766*4882a593Smuzhiyun 			  num_blocks * blksz);
767*4882a593Smuzhiyun 	if (ret < 0) {
768*4882a593Smuzhiyun 		BT_ERR("readsb failed: %d", ret);
769*4882a593Smuzhiyun 		ret = -EIO;
770*4882a593Smuzhiyun 		goto exit;
771*4882a593Smuzhiyun 	}
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	/* This is SDIO specific header length: byte[2][1][0], type: byte[3]
774*4882a593Smuzhiyun 	 * (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
775*4882a593Smuzhiyun 	 */
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	buf_len = payload[0];
778*4882a593Smuzhiyun 	buf_len |= payload[1] << 8;
779*4882a593Smuzhiyun 	buf_len |= payload[2] << 16;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	if (buf_len > blksz * num_blocks) {
782*4882a593Smuzhiyun 		BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
783*4882a593Smuzhiyun 		       buf_len, blksz * num_blocks);
784*4882a593Smuzhiyun 		ret = -EIO;
785*4882a593Smuzhiyun 		goto exit;
786*4882a593Smuzhiyun 	}
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	type = payload[3];
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	switch (type) {
791*4882a593Smuzhiyun 	case HCI_ACLDATA_PKT:
792*4882a593Smuzhiyun 	case HCI_SCODATA_PKT:
793*4882a593Smuzhiyun 	case HCI_EVENT_PKT:
794*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = type;
795*4882a593Smuzhiyun 		skb_put(skb, buf_len);
796*4882a593Smuzhiyun 		skb_pull(skb, SDIO_HEADER_LEN);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 		if (type == HCI_EVENT_PKT) {
799*4882a593Smuzhiyun 			if (btmrvl_check_evtpkt(priv, skb))
800*4882a593Smuzhiyun 				hci_recv_frame(hdev, skb);
801*4882a593Smuzhiyun 		} else {
802*4882a593Smuzhiyun 			hci_recv_frame(hdev, skb);
803*4882a593Smuzhiyun 		}
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 		hdev->stat.byte_rx += buf_len;
806*4882a593Smuzhiyun 		break;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	case MRVL_VENDOR_PKT:
809*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
810*4882a593Smuzhiyun 		skb_put(skb, buf_len);
811*4882a593Smuzhiyun 		skb_pull(skb, SDIO_HEADER_LEN);
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 		if (btmrvl_process_event(priv, skb))
814*4882a593Smuzhiyun 			hci_recv_frame(hdev, skb);
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 		hdev->stat.byte_rx += buf_len;
817*4882a593Smuzhiyun 		break;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	default:
820*4882a593Smuzhiyun 		BT_ERR("Unknown packet type:%d", type);
821*4882a593Smuzhiyun 		BT_ERR("hex: %*ph", blksz * num_blocks, payload);
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 		kfree_skb(skb);
824*4882a593Smuzhiyun 		skb = NULL;
825*4882a593Smuzhiyun 		break;
826*4882a593Smuzhiyun 	}
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun exit:
829*4882a593Smuzhiyun 	if (ret) {
830*4882a593Smuzhiyun 		hdev->stat.err_rx++;
831*4882a593Smuzhiyun 		kfree_skb(skb);
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	return ret;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun 
btmrvl_sdio_process_int_status(struct btmrvl_private * priv)837*4882a593Smuzhiyun static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun 	ulong flags;
840*4882a593Smuzhiyun 	u8 ireg;
841*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->driver_lock, flags);
844*4882a593Smuzhiyun 	ireg = sdio_ireg;
845*4882a593Smuzhiyun 	sdio_ireg = 0;
846*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->driver_lock, flags);
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	sdio_claim_host(card->func);
849*4882a593Smuzhiyun 	if (ireg & DN_LD_HOST_INT_STATUS) {
850*4882a593Smuzhiyun 		if (priv->btmrvl_dev.tx_dnld_rdy)
851*4882a593Smuzhiyun 			BT_DBG("tx_done already received: "
852*4882a593Smuzhiyun 				" int_status=0x%x", ireg);
853*4882a593Smuzhiyun 		else
854*4882a593Smuzhiyun 			priv->btmrvl_dev.tx_dnld_rdy = true;
855*4882a593Smuzhiyun 	}
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	if (ireg & UP_LD_HOST_INT_STATUS)
858*4882a593Smuzhiyun 		btmrvl_sdio_card_to_host(priv);
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	sdio_release_host(card->func);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	return 0;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun 
btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card * card,u8 * ireg)865*4882a593Smuzhiyun static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
866*4882a593Smuzhiyun {
867*4882a593Smuzhiyun 	struct btmrvl_adapter *adapter = card->priv->adapter;
868*4882a593Smuzhiyun 	int ret;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE);
871*4882a593Smuzhiyun 	if (ret) {
872*4882a593Smuzhiyun 		BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret);
873*4882a593Smuzhiyun 		return ret;
874*4882a593Smuzhiyun 	}
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	*ireg = adapter->hw_regs[card->reg->host_intstatus];
877*4882a593Smuzhiyun 	BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg);
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	return 0;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun 
btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card * card,u8 * ireg)882*4882a593Smuzhiyun static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun 	int ret;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	*ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
887*4882a593Smuzhiyun 	if (ret) {
888*4882a593Smuzhiyun 		BT_ERR("sdio_readb: read int status failed: %d", ret);
889*4882a593Smuzhiyun 		return ret;
890*4882a593Smuzhiyun 	}
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	if (*ireg) {
893*4882a593Smuzhiyun 		/*
894*4882a593Smuzhiyun 		 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
895*4882a593Smuzhiyun 		 * Clear the interrupt status register and re-enable the
896*4882a593Smuzhiyun 		 * interrupt.
897*4882a593Smuzhiyun 		 */
898*4882a593Smuzhiyun 		BT_DBG("int_status = 0x%x", *ireg);
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 		sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS |
901*4882a593Smuzhiyun 						    UP_LD_HOST_INT_STATUS),
902*4882a593Smuzhiyun 			    card->reg->host_intstatus, &ret);
903*4882a593Smuzhiyun 		if (ret) {
904*4882a593Smuzhiyun 			BT_ERR("sdio_writeb: clear int status failed: %d", ret);
905*4882a593Smuzhiyun 			return ret;
906*4882a593Smuzhiyun 		}
907*4882a593Smuzhiyun 	}
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	return 0;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun 
btmrvl_sdio_interrupt(struct sdio_func * func)912*4882a593Smuzhiyun static void btmrvl_sdio_interrupt(struct sdio_func *func)
913*4882a593Smuzhiyun {
914*4882a593Smuzhiyun 	struct btmrvl_private *priv;
915*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card;
916*4882a593Smuzhiyun 	ulong flags;
917*4882a593Smuzhiyun 	u8 ireg = 0;
918*4882a593Smuzhiyun 	int ret;
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	card = sdio_get_drvdata(func);
921*4882a593Smuzhiyun 	if (!card || !card->priv) {
922*4882a593Smuzhiyun 		BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
923*4882a593Smuzhiyun 		       func, card);
924*4882a593Smuzhiyun 		return;
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	priv = card->priv;
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 	if (priv->surprise_removed)
930*4882a593Smuzhiyun 		return;
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	if (card->reg->int_read_to_clear)
933*4882a593Smuzhiyun 		ret = btmrvl_sdio_read_to_clear(card, &ireg);
934*4882a593Smuzhiyun 	else
935*4882a593Smuzhiyun 		ret = btmrvl_sdio_write_to_clear(card, &ireg);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	if (ret)
938*4882a593Smuzhiyun 		return;
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->driver_lock, flags);
941*4882a593Smuzhiyun 	sdio_ireg |= ireg;
942*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->driver_lock, flags);
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	btmrvl_interrupt(priv);
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun 
btmrvl_sdio_register_dev(struct btmrvl_sdio_card * card)947*4882a593Smuzhiyun static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
948*4882a593Smuzhiyun {
949*4882a593Smuzhiyun 	struct sdio_func *func;
950*4882a593Smuzhiyun 	u8 reg;
951*4882a593Smuzhiyun 	int ret;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	if (!card || !card->func) {
954*4882a593Smuzhiyun 		BT_ERR("Error: card or function is NULL!");
955*4882a593Smuzhiyun 		ret = -EINVAL;
956*4882a593Smuzhiyun 		goto failed;
957*4882a593Smuzhiyun 	}
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	func = card->func;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	sdio_claim_host(func);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	ret = sdio_enable_func(func);
964*4882a593Smuzhiyun 	if (ret) {
965*4882a593Smuzhiyun 		BT_ERR("sdio_enable_func() failed: ret=%d", ret);
966*4882a593Smuzhiyun 		ret = -EIO;
967*4882a593Smuzhiyun 		goto release_host;
968*4882a593Smuzhiyun 	}
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	ret = sdio_claim_irq(func, btmrvl_sdio_interrupt);
971*4882a593Smuzhiyun 	if (ret) {
972*4882a593Smuzhiyun 		BT_ERR("sdio_claim_irq failed: ret=%d", ret);
973*4882a593Smuzhiyun 		ret = -EIO;
974*4882a593Smuzhiyun 		goto disable_func;
975*4882a593Smuzhiyun 	}
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun 	ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE);
978*4882a593Smuzhiyun 	if (ret) {
979*4882a593Smuzhiyun 		BT_ERR("cannot set SDIO block size");
980*4882a593Smuzhiyun 		ret = -EIO;
981*4882a593Smuzhiyun 		goto release_irq;
982*4882a593Smuzhiyun 	}
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	reg = sdio_readb(func, card->reg->io_port_0, &ret);
985*4882a593Smuzhiyun 	if (ret < 0) {
986*4882a593Smuzhiyun 		ret = -EIO;
987*4882a593Smuzhiyun 		goto release_irq;
988*4882a593Smuzhiyun 	}
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	card->ioport = reg;
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	reg = sdio_readb(func, card->reg->io_port_1, &ret);
993*4882a593Smuzhiyun 	if (ret < 0) {
994*4882a593Smuzhiyun 		ret = -EIO;
995*4882a593Smuzhiyun 		goto release_irq;
996*4882a593Smuzhiyun 	}
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	card->ioport |= (reg << 8);
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	reg = sdio_readb(func, card->reg->io_port_2, &ret);
1001*4882a593Smuzhiyun 	if (ret < 0) {
1002*4882a593Smuzhiyun 		ret = -EIO;
1003*4882a593Smuzhiyun 		goto release_irq;
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	card->ioport |= (reg << 16);
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	if (card->reg->int_read_to_clear) {
1011*4882a593Smuzhiyun 		reg = sdio_readb(func, card->reg->host_int_rsr, &ret);
1012*4882a593Smuzhiyun 		if (ret < 0) {
1013*4882a593Smuzhiyun 			ret = -EIO;
1014*4882a593Smuzhiyun 			goto release_irq;
1015*4882a593Smuzhiyun 		}
1016*4882a593Smuzhiyun 		sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret);
1017*4882a593Smuzhiyun 		if (ret < 0) {
1018*4882a593Smuzhiyun 			ret = -EIO;
1019*4882a593Smuzhiyun 			goto release_irq;
1020*4882a593Smuzhiyun 		}
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 		reg = sdio_readb(func, card->reg->card_misc_cfg, &ret);
1023*4882a593Smuzhiyun 		if (ret < 0) {
1024*4882a593Smuzhiyun 			ret = -EIO;
1025*4882a593Smuzhiyun 			goto release_irq;
1026*4882a593Smuzhiyun 		}
1027*4882a593Smuzhiyun 		sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret);
1028*4882a593Smuzhiyun 		if (ret < 0) {
1029*4882a593Smuzhiyun 			ret = -EIO;
1030*4882a593Smuzhiyun 			goto release_irq;
1031*4882a593Smuzhiyun 		}
1032*4882a593Smuzhiyun 	}
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	sdio_set_drvdata(func, card);
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	sdio_release_host(func);
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 	return 0;
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun release_irq:
1041*4882a593Smuzhiyun 	sdio_release_irq(func);
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun disable_func:
1044*4882a593Smuzhiyun 	sdio_disable_func(func);
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun release_host:
1047*4882a593Smuzhiyun 	sdio_release_host(func);
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun failed:
1050*4882a593Smuzhiyun 	return ret;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun 
btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card * card)1053*4882a593Smuzhiyun static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
1054*4882a593Smuzhiyun {
1055*4882a593Smuzhiyun 	if (card && card->func) {
1056*4882a593Smuzhiyun 		sdio_claim_host(card->func);
1057*4882a593Smuzhiyun 		sdio_release_irq(card->func);
1058*4882a593Smuzhiyun 		sdio_disable_func(card->func);
1059*4882a593Smuzhiyun 		sdio_release_host(card->func);
1060*4882a593Smuzhiyun 		sdio_set_drvdata(card->func, NULL);
1061*4882a593Smuzhiyun 	}
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun 	return 0;
1064*4882a593Smuzhiyun }
1065*4882a593Smuzhiyun 
btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card * card)1066*4882a593Smuzhiyun static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun 	int ret;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	if (!card || !card->func)
1071*4882a593Smuzhiyun 		return -EINVAL;
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	ret = btmrvl_sdio_enable_host_int_mask(card, HIM_ENABLE);
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	btmrvl_sdio_get_rx_unit(card);
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	sdio_release_host(card->func);
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	return ret;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun 
btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card * card)1084*4882a593Smuzhiyun static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun 	int ret;
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	if (!card || !card->func)
1089*4882a593Smuzhiyun 		return -EINVAL;
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	ret = btmrvl_sdio_disable_host_int_mask(card, HIM_DISABLE);
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	sdio_release_host(card->func);
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	return ret;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun 
btmrvl_sdio_host_to_card(struct btmrvl_private * priv,u8 * payload,u16 nb)1100*4882a593Smuzhiyun static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
1101*4882a593Smuzhiyun 				u8 *payload, u16 nb)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1104*4882a593Smuzhiyun 	int ret = 0;
1105*4882a593Smuzhiyun 	int blksz;
1106*4882a593Smuzhiyun 	int i = 0;
1107*4882a593Smuzhiyun 	u8 *buf = NULL;
1108*4882a593Smuzhiyun 	void *tmpbuf = NULL;
1109*4882a593Smuzhiyun 	int tmpbufsz;
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun 	if (!card || !card->func) {
1112*4882a593Smuzhiyun 		BT_ERR("card or function is NULL!");
1113*4882a593Smuzhiyun 		return -EINVAL;
1114*4882a593Smuzhiyun 	}
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 	blksz = DIV_ROUND_UP(nb, SDIO_BLOCK_SIZE) * SDIO_BLOCK_SIZE;
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	buf = payload;
1119*4882a593Smuzhiyun 	if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1) ||
1120*4882a593Smuzhiyun 	    nb < blksz) {
1121*4882a593Smuzhiyun 		tmpbufsz = ALIGN_SZ(blksz, BTSDIO_DMA_ALIGN) +
1122*4882a593Smuzhiyun 			   BTSDIO_DMA_ALIGN;
1123*4882a593Smuzhiyun 		tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL);
1124*4882a593Smuzhiyun 		if (!tmpbuf)
1125*4882a593Smuzhiyun 			return -ENOMEM;
1126*4882a593Smuzhiyun 		buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN);
1127*4882a593Smuzhiyun 		memcpy(buf, payload, nb);
1128*4882a593Smuzhiyun 	}
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	do {
1133*4882a593Smuzhiyun 		/* Transfer data to card */
1134*4882a593Smuzhiyun 		ret = sdio_writesb(card->func, card->ioport, buf,
1135*4882a593Smuzhiyun 				   blksz);
1136*4882a593Smuzhiyun 		if (ret < 0) {
1137*4882a593Smuzhiyun 			i++;
1138*4882a593Smuzhiyun 			BT_ERR("i=%d writesb failed: %d", i, ret);
1139*4882a593Smuzhiyun 			BT_ERR("hex: %*ph", nb, payload);
1140*4882a593Smuzhiyun 			ret = -EIO;
1141*4882a593Smuzhiyun 			if (i > MAX_WRITE_IOMEM_RETRY)
1142*4882a593Smuzhiyun 				goto exit;
1143*4882a593Smuzhiyun 		}
1144*4882a593Smuzhiyun 	} while (ret);
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun 	priv->btmrvl_dev.tx_dnld_rdy = false;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun exit:
1149*4882a593Smuzhiyun 	sdio_release_host(card->func);
1150*4882a593Smuzhiyun 	kfree(tmpbuf);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	return ret;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun 
btmrvl_sdio_download_fw(struct btmrvl_sdio_card * card)1155*4882a593Smuzhiyun static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun 	int ret;
1158*4882a593Smuzhiyun 	u8 fws0;
1159*4882a593Smuzhiyun 	int pollnum = MAX_POLL_TRIES;
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	if (!card || !card->func) {
1162*4882a593Smuzhiyun 		BT_ERR("card or function is NULL!");
1163*4882a593Smuzhiyun 		return -EINVAL;
1164*4882a593Smuzhiyun 	}
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	if (!btmrvl_sdio_verify_fw_download(card, 1)) {
1167*4882a593Smuzhiyun 		BT_DBG("Firmware already downloaded!");
1168*4882a593Smuzhiyun 		return 0;
1169*4882a593Smuzhiyun 	}
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	/* Check if other function driver is downloading the firmware */
1174*4882a593Smuzhiyun 	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
1175*4882a593Smuzhiyun 	if (ret) {
1176*4882a593Smuzhiyun 		BT_ERR("Failed to read FW downloading status!");
1177*4882a593Smuzhiyun 		ret = -EIO;
1178*4882a593Smuzhiyun 		goto done;
1179*4882a593Smuzhiyun 	}
1180*4882a593Smuzhiyun 	if (fws0) {
1181*4882a593Smuzhiyun 		BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 		/* Give other function more time to download the firmware */
1184*4882a593Smuzhiyun 		pollnum *= 10;
1185*4882a593Smuzhiyun 	} else {
1186*4882a593Smuzhiyun 		if (card->helper) {
1187*4882a593Smuzhiyun 			ret = btmrvl_sdio_download_helper(card);
1188*4882a593Smuzhiyun 			if (ret) {
1189*4882a593Smuzhiyun 				BT_ERR("Failed to download helper!");
1190*4882a593Smuzhiyun 				ret = -EIO;
1191*4882a593Smuzhiyun 				goto done;
1192*4882a593Smuzhiyun 			}
1193*4882a593Smuzhiyun 		}
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 		if (btmrvl_sdio_download_fw_w_helper(card)) {
1196*4882a593Smuzhiyun 			BT_ERR("Failed to download firmware!");
1197*4882a593Smuzhiyun 			ret = -EIO;
1198*4882a593Smuzhiyun 			goto done;
1199*4882a593Smuzhiyun 		}
1200*4882a593Smuzhiyun 	}
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	/*
1203*4882a593Smuzhiyun 	 * winner or not, with this test the FW synchronizes when the
1204*4882a593Smuzhiyun 	 * module can continue its initialization
1205*4882a593Smuzhiyun 	 */
1206*4882a593Smuzhiyun 	if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
1207*4882a593Smuzhiyun 		BT_ERR("FW failed to be active in time!");
1208*4882a593Smuzhiyun 		ret = -ETIMEDOUT;
1209*4882a593Smuzhiyun 		goto done;
1210*4882a593Smuzhiyun 	}
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 	sdio_release_host(card->func);
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun 	return 0;
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun done:
1217*4882a593Smuzhiyun 	sdio_release_host(card->func);
1218*4882a593Smuzhiyun 	return ret;
1219*4882a593Smuzhiyun }
1220*4882a593Smuzhiyun 
btmrvl_sdio_wakeup_fw(struct btmrvl_private * priv)1221*4882a593Smuzhiyun static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
1222*4882a593Smuzhiyun {
1223*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1224*4882a593Smuzhiyun 	int ret = 0;
1225*4882a593Smuzhiyun 
1226*4882a593Smuzhiyun 	if (!card || !card->func) {
1227*4882a593Smuzhiyun 		BT_ERR("card or function is NULL!");
1228*4882a593Smuzhiyun 		return -EINVAL;
1229*4882a593Smuzhiyun 	}
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	sdio_release_host(card->func);
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	BT_DBG("wake up firmware");
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun 	return ret;
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun 
btmrvl_sdio_dump_regs(struct btmrvl_private * priv)1242*4882a593Smuzhiyun static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1245*4882a593Smuzhiyun 	int ret = 0;
1246*4882a593Smuzhiyun 	unsigned int reg, reg_start, reg_end;
1247*4882a593Smuzhiyun 	char buf[256], *ptr;
1248*4882a593Smuzhiyun 	u8 loop, func, data;
1249*4882a593Smuzhiyun 	int MAX_LOOP = 2;
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun 	btmrvl_sdio_wakeup_fw(priv);
1252*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	for (loop = 0; loop < MAX_LOOP; loop++) {
1255*4882a593Smuzhiyun 		memset(buf, 0, sizeof(buf));
1256*4882a593Smuzhiyun 		ptr = buf;
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun 		if (loop == 0) {
1259*4882a593Smuzhiyun 			/* Read the registers of SDIO function0 */
1260*4882a593Smuzhiyun 			func = loop;
1261*4882a593Smuzhiyun 			reg_start = 0;
1262*4882a593Smuzhiyun 			reg_end = 9;
1263*4882a593Smuzhiyun 		} else {
1264*4882a593Smuzhiyun 			func = 2;
1265*4882a593Smuzhiyun 			reg_start = 0;
1266*4882a593Smuzhiyun 			reg_end = 0x09;
1267*4882a593Smuzhiyun 		}
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun 		ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
1270*4882a593Smuzhiyun 			       func, reg_start, reg_end);
1271*4882a593Smuzhiyun 		for (reg = reg_start; reg <= reg_end; reg++) {
1272*4882a593Smuzhiyun 			if (func == 0)
1273*4882a593Smuzhiyun 				data = sdio_f0_readb(card->func, reg, &ret);
1274*4882a593Smuzhiyun 			else
1275*4882a593Smuzhiyun 				data = sdio_readb(card->func, reg, &ret);
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 			if (!ret) {
1278*4882a593Smuzhiyun 				ptr += sprintf(ptr, "%02x ", data);
1279*4882a593Smuzhiyun 			} else {
1280*4882a593Smuzhiyun 				ptr += sprintf(ptr, "ERR");
1281*4882a593Smuzhiyun 				break;
1282*4882a593Smuzhiyun 			}
1283*4882a593Smuzhiyun 		}
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun 		BT_INFO("%s", buf);
1286*4882a593Smuzhiyun 	}
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun 	sdio_release_host(card->func);
1289*4882a593Smuzhiyun }
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun /* This function read/write firmware */
1292*4882a593Smuzhiyun static enum
btmrvl_sdio_rdwr_firmware(struct btmrvl_private * priv,u8 doneflag)1293*4882a593Smuzhiyun rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
1294*4882a593Smuzhiyun 				      u8 doneflag)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
1297*4882a593Smuzhiyun 	int ret, tries;
1298*4882a593Smuzhiyun 	u8 ctrl_data = 0;
1299*4882a593Smuzhiyun 
1300*4882a593Smuzhiyun 	sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
1301*4882a593Smuzhiyun 		    &ret);
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	if (ret) {
1304*4882a593Smuzhiyun 		BT_ERR("SDIO write err");
1305*4882a593Smuzhiyun 		return RDWR_STATUS_FAILURE;
1306*4882a593Smuzhiyun 	}
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun 	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1309*4882a593Smuzhiyun 		ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
1310*4882a593Smuzhiyun 				       &ret);
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 		if (ret) {
1313*4882a593Smuzhiyun 			BT_ERR("SDIO read err");
1314*4882a593Smuzhiyun 			return RDWR_STATUS_FAILURE;
1315*4882a593Smuzhiyun 		}
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 		if (ctrl_data == FW_DUMP_DONE)
1318*4882a593Smuzhiyun 			break;
1319*4882a593Smuzhiyun 		if (doneflag && ctrl_data == doneflag)
1320*4882a593Smuzhiyun 			return RDWR_STATUS_DONE;
1321*4882a593Smuzhiyun 		if (ctrl_data != FW_DUMP_HOST_READY) {
1322*4882a593Smuzhiyun 			BT_INFO("The ctrl reg was changed, re-try again!");
1323*4882a593Smuzhiyun 			sdio_writeb(card->func, FW_DUMP_HOST_READY,
1324*4882a593Smuzhiyun 				    card->reg->fw_dump_ctrl, &ret);
1325*4882a593Smuzhiyun 			if (ret) {
1326*4882a593Smuzhiyun 				BT_ERR("SDIO write err");
1327*4882a593Smuzhiyun 				return RDWR_STATUS_FAILURE;
1328*4882a593Smuzhiyun 			}
1329*4882a593Smuzhiyun 		}
1330*4882a593Smuzhiyun 		usleep_range(100, 200);
1331*4882a593Smuzhiyun 	}
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	if (ctrl_data == FW_DUMP_HOST_READY) {
1334*4882a593Smuzhiyun 		BT_ERR("Fail to pull ctrl_data");
1335*4882a593Smuzhiyun 		return RDWR_STATUS_FAILURE;
1336*4882a593Smuzhiyun 	}
1337*4882a593Smuzhiyun 
1338*4882a593Smuzhiyun 	return RDWR_STATUS_SUCCESS;
1339*4882a593Smuzhiyun }
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun /* This function dump sdio register and memory data */
btmrvl_sdio_coredump(struct device * dev)1342*4882a593Smuzhiyun static void btmrvl_sdio_coredump(struct device *dev)
1343*4882a593Smuzhiyun {
1344*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(dev);
1345*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card;
1346*4882a593Smuzhiyun 	struct btmrvl_private *priv;
1347*4882a593Smuzhiyun 	int ret = 0;
1348*4882a593Smuzhiyun 	unsigned int reg, reg_start, reg_end;
1349*4882a593Smuzhiyun 	enum rdwr_status stat;
1350*4882a593Smuzhiyun 	u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
1351*4882a593Smuzhiyun 	u8 dump_num = 0, idx, i, read_reg, doneflag = 0;
1352*4882a593Smuzhiyun 	u32 memory_size, fw_dump_len = 0;
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun 	card = sdio_get_drvdata(func);
1355*4882a593Smuzhiyun 	priv = card->priv;
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun 	/* dump sdio register first */
1358*4882a593Smuzhiyun 	btmrvl_sdio_dump_regs(priv);
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun 	if (!card->supports_fw_dump) {
1361*4882a593Smuzhiyun 		BT_ERR("Firmware dump not supported for this card!");
1362*4882a593Smuzhiyun 		return;
1363*4882a593Smuzhiyun 	}
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun 	for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
1366*4882a593Smuzhiyun 		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 		if (entry->mem_ptr) {
1369*4882a593Smuzhiyun 			vfree(entry->mem_ptr);
1370*4882a593Smuzhiyun 			entry->mem_ptr = NULL;
1371*4882a593Smuzhiyun 		}
1372*4882a593Smuzhiyun 		entry->mem_size = 0;
1373*4882a593Smuzhiyun 	}
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	btmrvl_sdio_wakeup_fw(priv);
1376*4882a593Smuzhiyun 	sdio_claim_host(card->func);
1377*4882a593Smuzhiyun 
1378*4882a593Smuzhiyun 	BT_INFO("== btmrvl firmware dump start ==");
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 	stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1381*4882a593Smuzhiyun 	if (stat == RDWR_STATUS_FAILURE)
1382*4882a593Smuzhiyun 		goto done;
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	reg = card->reg->fw_dump_start;
1385*4882a593Smuzhiyun 	/* Read the number of the memories which will dump */
1386*4882a593Smuzhiyun 	dump_num = sdio_readb(card->func, reg, &ret);
1387*4882a593Smuzhiyun 
1388*4882a593Smuzhiyun 	if (ret) {
1389*4882a593Smuzhiyun 		BT_ERR("SDIO read memory length err");
1390*4882a593Smuzhiyun 		goto done;
1391*4882a593Smuzhiyun 	}
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 	/* Read the length of every memory which will dump */
1394*4882a593Smuzhiyun 	for (idx = 0; idx < dump_num; idx++) {
1395*4882a593Smuzhiyun 		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 		stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1398*4882a593Smuzhiyun 		if (stat == RDWR_STATUS_FAILURE)
1399*4882a593Smuzhiyun 			goto done;
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun 		memory_size = 0;
1402*4882a593Smuzhiyun 		reg = card->reg->fw_dump_start;
1403*4882a593Smuzhiyun 		for (i = 0; i < 4; i++) {
1404*4882a593Smuzhiyun 			read_reg = sdio_readb(card->func, reg, &ret);
1405*4882a593Smuzhiyun 			if (ret) {
1406*4882a593Smuzhiyun 				BT_ERR("SDIO read err");
1407*4882a593Smuzhiyun 				goto done;
1408*4882a593Smuzhiyun 			}
1409*4882a593Smuzhiyun 			memory_size |= (read_reg << i*8);
1410*4882a593Smuzhiyun 			reg++;
1411*4882a593Smuzhiyun 		}
1412*4882a593Smuzhiyun 
1413*4882a593Smuzhiyun 		if (memory_size == 0) {
1414*4882a593Smuzhiyun 			BT_INFO("Firmware dump finished!");
1415*4882a593Smuzhiyun 			sdio_writeb(card->func, FW_DUMP_READ_DONE,
1416*4882a593Smuzhiyun 				    card->reg->fw_dump_ctrl, &ret);
1417*4882a593Smuzhiyun 			if (ret) {
1418*4882a593Smuzhiyun 				BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
1419*4882a593Smuzhiyun 				goto done;
1420*4882a593Smuzhiyun 			}
1421*4882a593Smuzhiyun 			break;
1422*4882a593Smuzhiyun 		}
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun 		BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
1425*4882a593Smuzhiyun 		entry->mem_ptr = vzalloc(memory_size + 1);
1426*4882a593Smuzhiyun 		entry->mem_size = memory_size;
1427*4882a593Smuzhiyun 		if (!entry->mem_ptr) {
1428*4882a593Smuzhiyun 			BT_ERR("Vzalloc %s failed", entry->mem_name);
1429*4882a593Smuzhiyun 			goto done;
1430*4882a593Smuzhiyun 		}
1431*4882a593Smuzhiyun 
1432*4882a593Smuzhiyun 		fw_dump_len += (strlen("========Start dump ") +
1433*4882a593Smuzhiyun 				strlen(entry->mem_name) +
1434*4882a593Smuzhiyun 				strlen("========\n") +
1435*4882a593Smuzhiyun 				(memory_size + 1) +
1436*4882a593Smuzhiyun 				strlen("\n========End dump========\n"));
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun 		dbg_ptr = entry->mem_ptr;
1439*4882a593Smuzhiyun 		end_ptr = dbg_ptr + memory_size;
1440*4882a593Smuzhiyun 
1441*4882a593Smuzhiyun 		doneflag = entry->done_flag;
1442*4882a593Smuzhiyun 		BT_INFO("Start %s output, please wait...",
1443*4882a593Smuzhiyun 			entry->mem_name);
1444*4882a593Smuzhiyun 
1445*4882a593Smuzhiyun 		do {
1446*4882a593Smuzhiyun 			stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
1447*4882a593Smuzhiyun 			if (stat == RDWR_STATUS_FAILURE)
1448*4882a593Smuzhiyun 				goto done;
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun 			reg_start = card->reg->fw_dump_start;
1451*4882a593Smuzhiyun 			reg_end = card->reg->fw_dump_end;
1452*4882a593Smuzhiyun 			for (reg = reg_start; reg <= reg_end; reg++) {
1453*4882a593Smuzhiyun 				*dbg_ptr = sdio_readb(card->func, reg, &ret);
1454*4882a593Smuzhiyun 				if (ret) {
1455*4882a593Smuzhiyun 					BT_ERR("SDIO read err");
1456*4882a593Smuzhiyun 					goto done;
1457*4882a593Smuzhiyun 				}
1458*4882a593Smuzhiyun 				if (dbg_ptr < end_ptr)
1459*4882a593Smuzhiyun 					dbg_ptr++;
1460*4882a593Smuzhiyun 				else
1461*4882a593Smuzhiyun 					BT_ERR("Allocated buffer not enough");
1462*4882a593Smuzhiyun 			}
1463*4882a593Smuzhiyun 
1464*4882a593Smuzhiyun 			if (stat != RDWR_STATUS_DONE) {
1465*4882a593Smuzhiyun 				continue;
1466*4882a593Smuzhiyun 			} else {
1467*4882a593Smuzhiyun 				BT_INFO("%s done: size=0x%tx",
1468*4882a593Smuzhiyun 					entry->mem_name,
1469*4882a593Smuzhiyun 					dbg_ptr - entry->mem_ptr);
1470*4882a593Smuzhiyun 				break;
1471*4882a593Smuzhiyun 			}
1472*4882a593Smuzhiyun 		} while (1);
1473*4882a593Smuzhiyun 	}
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 	BT_INFO("== btmrvl firmware dump end ==");
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun done:
1478*4882a593Smuzhiyun 	sdio_release_host(card->func);
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	if (fw_dump_len == 0)
1481*4882a593Smuzhiyun 		return;
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	fw_dump_data = vzalloc(fw_dump_len+1);
1484*4882a593Smuzhiyun 	if (!fw_dump_data) {
1485*4882a593Smuzhiyun 		BT_ERR("Vzalloc fw_dump_data fail!");
1486*4882a593Smuzhiyun 		return;
1487*4882a593Smuzhiyun 	}
1488*4882a593Smuzhiyun 	fw_dump_ptr = fw_dump_data;
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun 	/* Dump all the memory data into single file, a userspace script will
1491*4882a593Smuzhiyun 	 * be used to split all the memory data to multiple files
1492*4882a593Smuzhiyun 	 */
1493*4882a593Smuzhiyun 	BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
1494*4882a593Smuzhiyun 	for (idx = 0; idx < dump_num; idx++) {
1495*4882a593Smuzhiyun 		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 		if (entry->mem_ptr) {
1498*4882a593Smuzhiyun 			strcpy(fw_dump_ptr, "========Start dump ");
1499*4882a593Smuzhiyun 			fw_dump_ptr += strlen("========Start dump ");
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun 			strcpy(fw_dump_ptr, entry->mem_name);
1502*4882a593Smuzhiyun 			fw_dump_ptr += strlen(entry->mem_name);
1503*4882a593Smuzhiyun 
1504*4882a593Smuzhiyun 			strcpy(fw_dump_ptr, "========\n");
1505*4882a593Smuzhiyun 			fw_dump_ptr += strlen("========\n");
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun 			memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
1508*4882a593Smuzhiyun 			fw_dump_ptr += entry->mem_size;
1509*4882a593Smuzhiyun 
1510*4882a593Smuzhiyun 			strcpy(fw_dump_ptr, "\n========End dump========\n");
1511*4882a593Smuzhiyun 			fw_dump_ptr += strlen("\n========End dump========\n");
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun 			vfree(mem_type_mapping_tbl[idx].mem_ptr);
1514*4882a593Smuzhiyun 			mem_type_mapping_tbl[idx].mem_ptr = NULL;
1515*4882a593Smuzhiyun 		}
1516*4882a593Smuzhiyun 	}
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun 	/* fw_dump_data will be free in device coredump release function
1519*4882a593Smuzhiyun 	 * after 5 min
1520*4882a593Smuzhiyun 	 */
1521*4882a593Smuzhiyun 	dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL);
1522*4882a593Smuzhiyun 	BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
1523*4882a593Smuzhiyun }
1524*4882a593Smuzhiyun 
btmrvl_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)1525*4882a593Smuzhiyun static int btmrvl_sdio_probe(struct sdio_func *func,
1526*4882a593Smuzhiyun 					const struct sdio_device_id *id)
1527*4882a593Smuzhiyun {
1528*4882a593Smuzhiyun 	int ret = 0;
1529*4882a593Smuzhiyun 	struct btmrvl_private *priv = NULL;
1530*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card = NULL;
1531*4882a593Smuzhiyun 
1532*4882a593Smuzhiyun 	BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
1533*4882a593Smuzhiyun 			id->vendor, id->device, id->class, func->num);
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun 	card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
1536*4882a593Smuzhiyun 	if (!card)
1537*4882a593Smuzhiyun 		return -ENOMEM;
1538*4882a593Smuzhiyun 
1539*4882a593Smuzhiyun 	card->func = func;
1540*4882a593Smuzhiyun 
1541*4882a593Smuzhiyun 	if (id->driver_data) {
1542*4882a593Smuzhiyun 		struct btmrvl_sdio_device *data = (void *) id->driver_data;
1543*4882a593Smuzhiyun 		card->helper = data->helper;
1544*4882a593Smuzhiyun 		card->firmware = data->firmware;
1545*4882a593Smuzhiyun 		card->reg = data->reg;
1546*4882a593Smuzhiyun 		card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
1547*4882a593Smuzhiyun 		card->support_pscan_win_report = data->support_pscan_win_report;
1548*4882a593Smuzhiyun 		card->supports_fw_dump = data->supports_fw_dump;
1549*4882a593Smuzhiyun 	}
1550*4882a593Smuzhiyun 
1551*4882a593Smuzhiyun 	if (btmrvl_sdio_register_dev(card) < 0) {
1552*4882a593Smuzhiyun 		BT_ERR("Failed to register BT device!");
1553*4882a593Smuzhiyun 		return -ENODEV;
1554*4882a593Smuzhiyun 	}
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 	/* Disable the interrupts on the card */
1557*4882a593Smuzhiyun 	btmrvl_sdio_disable_host_int(card);
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun 	if (btmrvl_sdio_download_fw(card)) {
1560*4882a593Smuzhiyun 		BT_ERR("Downloading firmware failed!");
1561*4882a593Smuzhiyun 		ret = -ENODEV;
1562*4882a593Smuzhiyun 		goto unreg_dev;
1563*4882a593Smuzhiyun 	}
1564*4882a593Smuzhiyun 
1565*4882a593Smuzhiyun 	btmrvl_sdio_enable_host_int(card);
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	/* Device tree node parsing and platform specific configuration*/
1568*4882a593Smuzhiyun 	btmrvl_sdio_probe_of(&func->dev, card);
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun 	priv = btmrvl_add_card(card);
1571*4882a593Smuzhiyun 	if (!priv) {
1572*4882a593Smuzhiyun 		BT_ERR("Initializing card failed!");
1573*4882a593Smuzhiyun 		ret = -ENODEV;
1574*4882a593Smuzhiyun 		goto disable_host_int;
1575*4882a593Smuzhiyun 	}
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun 	card->priv = priv;
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun 	/* Initialize the interface specific function pointers */
1580*4882a593Smuzhiyun 	priv->hw_host_to_card = btmrvl_sdio_host_to_card;
1581*4882a593Smuzhiyun 	priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
1582*4882a593Smuzhiyun 	priv->hw_process_int_status = btmrvl_sdio_process_int_status;
1583*4882a593Smuzhiyun 
1584*4882a593Smuzhiyun 	if (btmrvl_register_hdev(priv)) {
1585*4882a593Smuzhiyun 		BT_ERR("Register hdev failed!");
1586*4882a593Smuzhiyun 		ret = -ENODEV;
1587*4882a593Smuzhiyun 		goto disable_host_int;
1588*4882a593Smuzhiyun 	}
1589*4882a593Smuzhiyun 
1590*4882a593Smuzhiyun 	return 0;
1591*4882a593Smuzhiyun 
1592*4882a593Smuzhiyun disable_host_int:
1593*4882a593Smuzhiyun 	btmrvl_sdio_disable_host_int(card);
1594*4882a593Smuzhiyun unreg_dev:
1595*4882a593Smuzhiyun 	btmrvl_sdio_unregister_dev(card);
1596*4882a593Smuzhiyun 	return ret;
1597*4882a593Smuzhiyun }
1598*4882a593Smuzhiyun 
btmrvl_sdio_remove(struct sdio_func * func)1599*4882a593Smuzhiyun static void btmrvl_sdio_remove(struct sdio_func *func)
1600*4882a593Smuzhiyun {
1601*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card;
1602*4882a593Smuzhiyun 
1603*4882a593Smuzhiyun 	if (func) {
1604*4882a593Smuzhiyun 		card = sdio_get_drvdata(func);
1605*4882a593Smuzhiyun 		if (card) {
1606*4882a593Smuzhiyun 			/* Send SHUTDOWN command & disable interrupt
1607*4882a593Smuzhiyun 			 * if user removes the module.
1608*4882a593Smuzhiyun 			 */
1609*4882a593Smuzhiyun 			if (user_rmmod) {
1610*4882a593Smuzhiyun 				btmrvl_send_module_cfg_cmd(card->priv,
1611*4882a593Smuzhiyun 							MODULE_SHUTDOWN_REQ);
1612*4882a593Smuzhiyun 				btmrvl_sdio_disable_host_int(card);
1613*4882a593Smuzhiyun 			}
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun 			BT_DBG("unregister dev");
1616*4882a593Smuzhiyun 			card->priv->surprise_removed = true;
1617*4882a593Smuzhiyun 			btmrvl_sdio_unregister_dev(card);
1618*4882a593Smuzhiyun 			btmrvl_remove_card(card->priv);
1619*4882a593Smuzhiyun 		}
1620*4882a593Smuzhiyun 	}
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun 
btmrvl_sdio_suspend(struct device * dev)1623*4882a593Smuzhiyun static int btmrvl_sdio_suspend(struct device *dev)
1624*4882a593Smuzhiyun {
1625*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(dev);
1626*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card;
1627*4882a593Smuzhiyun 	struct btmrvl_private *priv;
1628*4882a593Smuzhiyun 	mmc_pm_flag_t pm_flags;
1629*4882a593Smuzhiyun 	struct hci_dev *hcidev;
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 	if (func) {
1632*4882a593Smuzhiyun 		pm_flags = sdio_get_host_pm_caps(func);
1633*4882a593Smuzhiyun 		BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func),
1634*4882a593Smuzhiyun 		       pm_flags);
1635*4882a593Smuzhiyun 		if (!(pm_flags & MMC_PM_KEEP_POWER)) {
1636*4882a593Smuzhiyun 			BT_ERR("%s: cannot remain alive while suspended",
1637*4882a593Smuzhiyun 			       sdio_func_id(func));
1638*4882a593Smuzhiyun 			return -ENOSYS;
1639*4882a593Smuzhiyun 		}
1640*4882a593Smuzhiyun 		card = sdio_get_drvdata(func);
1641*4882a593Smuzhiyun 		if (!card || !card->priv) {
1642*4882a593Smuzhiyun 			BT_ERR("card or priv structure is not valid");
1643*4882a593Smuzhiyun 			return 0;
1644*4882a593Smuzhiyun 		}
1645*4882a593Smuzhiyun 	} else {
1646*4882a593Smuzhiyun 		BT_ERR("sdio_func is not specified");
1647*4882a593Smuzhiyun 		return 0;
1648*4882a593Smuzhiyun 	}
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun 	/* Enable platform specific wakeup interrupt */
1651*4882a593Smuzhiyun 	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
1652*4882a593Smuzhiyun 	    device_may_wakeup(dev)) {
1653*4882a593Smuzhiyun 		card->plt_wake_cfg->wake_by_bt = false;
1654*4882a593Smuzhiyun 		enable_irq(card->plt_wake_cfg->irq_bt);
1655*4882a593Smuzhiyun 		enable_irq_wake(card->plt_wake_cfg->irq_bt);
1656*4882a593Smuzhiyun 	}
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 	priv = card->priv;
1659*4882a593Smuzhiyun 	priv->adapter->is_suspending = true;
1660*4882a593Smuzhiyun 	hcidev = priv->btmrvl_dev.hcidev;
1661*4882a593Smuzhiyun 	BT_DBG("%s: SDIO suspend", hcidev->name);
1662*4882a593Smuzhiyun 	hci_suspend_dev(hcidev);
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	if (priv->adapter->hs_state != HS_ACTIVATED) {
1665*4882a593Smuzhiyun 		if (btmrvl_enable_hs(priv)) {
1666*4882a593Smuzhiyun 			BT_ERR("HS not activated, suspend failed!");
1667*4882a593Smuzhiyun 			/* Disable platform specific wakeup interrupt */
1668*4882a593Smuzhiyun 			if (card->plt_wake_cfg &&
1669*4882a593Smuzhiyun 			    card->plt_wake_cfg->irq_bt >= 0 &&
1670*4882a593Smuzhiyun 			    device_may_wakeup(dev)) {
1671*4882a593Smuzhiyun 				disable_irq_wake(card->plt_wake_cfg->irq_bt);
1672*4882a593Smuzhiyun 				disable_irq(card->plt_wake_cfg->irq_bt);
1673*4882a593Smuzhiyun 			}
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 			priv->adapter->is_suspending = false;
1676*4882a593Smuzhiyun 			return -EBUSY;
1677*4882a593Smuzhiyun 		}
1678*4882a593Smuzhiyun 	}
1679*4882a593Smuzhiyun 
1680*4882a593Smuzhiyun 	priv->adapter->is_suspending = false;
1681*4882a593Smuzhiyun 	priv->adapter->is_suspended = true;
1682*4882a593Smuzhiyun 
1683*4882a593Smuzhiyun 	/* We will keep the power when hs enabled successfully */
1684*4882a593Smuzhiyun 	if (priv->adapter->hs_state == HS_ACTIVATED) {
1685*4882a593Smuzhiyun 		BT_DBG("suspend with MMC_PM_KEEP_POWER");
1686*4882a593Smuzhiyun 		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
1687*4882a593Smuzhiyun 	}
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 	BT_DBG("suspend without MMC_PM_KEEP_POWER");
1690*4882a593Smuzhiyun 	return 0;
1691*4882a593Smuzhiyun }
1692*4882a593Smuzhiyun 
btmrvl_sdio_resume(struct device * dev)1693*4882a593Smuzhiyun static int btmrvl_sdio_resume(struct device *dev)
1694*4882a593Smuzhiyun {
1695*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(dev);
1696*4882a593Smuzhiyun 	struct btmrvl_sdio_card *card;
1697*4882a593Smuzhiyun 	struct btmrvl_private *priv;
1698*4882a593Smuzhiyun 	mmc_pm_flag_t pm_flags;
1699*4882a593Smuzhiyun 	struct hci_dev *hcidev;
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun 	if (func) {
1702*4882a593Smuzhiyun 		pm_flags = sdio_get_host_pm_caps(func);
1703*4882a593Smuzhiyun 		BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func),
1704*4882a593Smuzhiyun 		       pm_flags);
1705*4882a593Smuzhiyun 		card = sdio_get_drvdata(func);
1706*4882a593Smuzhiyun 		if (!card || !card->priv) {
1707*4882a593Smuzhiyun 			BT_ERR("card or priv structure is not valid");
1708*4882a593Smuzhiyun 			return 0;
1709*4882a593Smuzhiyun 		}
1710*4882a593Smuzhiyun 	} else {
1711*4882a593Smuzhiyun 		BT_ERR("sdio_func is not specified");
1712*4882a593Smuzhiyun 		return 0;
1713*4882a593Smuzhiyun 	}
1714*4882a593Smuzhiyun 	priv = card->priv;
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun 	if (!priv->adapter->is_suspended) {
1717*4882a593Smuzhiyun 		BT_DBG("device already resumed");
1718*4882a593Smuzhiyun 		return 0;
1719*4882a593Smuzhiyun 	}
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	priv->hw_wakeup_firmware(priv);
1722*4882a593Smuzhiyun 	priv->adapter->hs_state = HS_DEACTIVATED;
1723*4882a593Smuzhiyun 	hcidev = priv->btmrvl_dev.hcidev;
1724*4882a593Smuzhiyun 	BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
1725*4882a593Smuzhiyun 	priv->adapter->is_suspended = false;
1726*4882a593Smuzhiyun 	BT_DBG("%s: SDIO resume", hcidev->name);
1727*4882a593Smuzhiyun 	hci_resume_dev(hcidev);
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun 	/* Disable platform specific wakeup interrupt */
1730*4882a593Smuzhiyun 	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
1731*4882a593Smuzhiyun 	    device_may_wakeup(dev)) {
1732*4882a593Smuzhiyun 		disable_irq_wake(card->plt_wake_cfg->irq_bt);
1733*4882a593Smuzhiyun 		disable_irq(card->plt_wake_cfg->irq_bt);
1734*4882a593Smuzhiyun 		if (card->plt_wake_cfg->wake_by_bt)
1735*4882a593Smuzhiyun 			/* Undo our disable, since interrupt handler already
1736*4882a593Smuzhiyun 			 * did this.
1737*4882a593Smuzhiyun 			 */
1738*4882a593Smuzhiyun 			enable_irq(card->plt_wake_cfg->irq_bt);
1739*4882a593Smuzhiyun 	}
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	return 0;
1742*4882a593Smuzhiyun }
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun static const struct dev_pm_ops btmrvl_sdio_pm_ops = {
1745*4882a593Smuzhiyun 	.suspend	= btmrvl_sdio_suspend,
1746*4882a593Smuzhiyun 	.resume		= btmrvl_sdio_resume,
1747*4882a593Smuzhiyun };
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun static struct sdio_driver bt_mrvl_sdio = {
1750*4882a593Smuzhiyun 	.name		= "btmrvl_sdio",
1751*4882a593Smuzhiyun 	.id_table	= btmrvl_sdio_ids,
1752*4882a593Smuzhiyun 	.probe		= btmrvl_sdio_probe,
1753*4882a593Smuzhiyun 	.remove		= btmrvl_sdio_remove,
1754*4882a593Smuzhiyun 	.drv = {
1755*4882a593Smuzhiyun 		.owner = THIS_MODULE,
1756*4882a593Smuzhiyun 		.coredump = btmrvl_sdio_coredump,
1757*4882a593Smuzhiyun 		.pm = &btmrvl_sdio_pm_ops,
1758*4882a593Smuzhiyun 	}
1759*4882a593Smuzhiyun };
1760*4882a593Smuzhiyun 
btmrvl_sdio_init_module(void)1761*4882a593Smuzhiyun static int __init btmrvl_sdio_init_module(void)
1762*4882a593Smuzhiyun {
1763*4882a593Smuzhiyun 	if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
1764*4882a593Smuzhiyun 		BT_ERR("SDIO Driver Registration Failed");
1765*4882a593Smuzhiyun 		return -ENODEV;
1766*4882a593Smuzhiyun 	}
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun 	/* Clear the flag in case user removes the card. */
1769*4882a593Smuzhiyun 	user_rmmod = 0;
1770*4882a593Smuzhiyun 
1771*4882a593Smuzhiyun 	return 0;
1772*4882a593Smuzhiyun }
1773*4882a593Smuzhiyun 
btmrvl_sdio_exit_module(void)1774*4882a593Smuzhiyun static void __exit btmrvl_sdio_exit_module(void)
1775*4882a593Smuzhiyun {
1776*4882a593Smuzhiyun 	/* Set the flag as user is removing this module. */
1777*4882a593Smuzhiyun 	user_rmmod = 1;
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun 	sdio_unregister_driver(&bt_mrvl_sdio);
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun module_init(btmrvl_sdio_init_module);
1783*4882a593Smuzhiyun module_exit(btmrvl_sdio_exit_module);
1784*4882a593Smuzhiyun 
1785*4882a593Smuzhiyun MODULE_AUTHOR("Marvell International Ltd.");
1786*4882a593Smuzhiyun MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
1787*4882a593Smuzhiyun MODULE_VERSION(VERSION);
1788*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1789*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
1790*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8688.bin");
1791*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
1792*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
1793*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
1794*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
1795*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sdsd8977_combo_v2.bin");
1796*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sd8987_uapsta.bin");
1797*4882a593Smuzhiyun MODULE_FIRMWARE("mrvl/sdsd8997_combo_v4.bin");
1798