1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * |
4 | * Generic Bluetooth SDIO driver |
5 | * |
6 | * Copyright (C) 2007 Cambridge Silicon Radio Ltd. |
7 | * Copyright (C) 2007 Marcel Holtmann <marcel@holtmann.org> |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/init.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/types.h> |
15 | #include <linux/sched.h> |
16 | #include <linux/errno.h> |
17 | #include <linux/skbuff.h> |
18 | |
19 | #include <linux/mmc/host.h> |
20 | #include <linux/mmc/sdio_ids.h> |
21 | #include <linux/mmc/sdio_func.h> |
22 | |
23 | #include <net/bluetooth/bluetooth.h> |
24 | #include <net/bluetooth/hci_core.h> |
25 | |
26 | #define VERSION "0.1" |
27 | |
28 | static const struct sdio_device_id btsdio_table[] = { |
29 | /* Generic Bluetooth Type-A SDIO device */ |
30 | { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_A) }, |
31 | |
32 | /* Generic Bluetooth Type-B SDIO device */ |
33 | { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) }, |
34 | |
35 | /* Generic Bluetooth AMP controller */ |
36 | { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) }, |
37 | |
38 | { } /* Terminating entry */ |
39 | }; |
40 | |
41 | MODULE_DEVICE_TABLE(sdio, btsdio_table); |
42 | |
43 | struct btsdio_data { |
44 | struct hci_dev *hdev; |
45 | struct sdio_func *func; |
46 | |
47 | struct work_struct work; |
48 | |
49 | struct sk_buff_head txq; |
50 | }; |
51 | |
52 | #define REG_RDAT 0x00 /* Receiver Data */ |
53 | #define REG_TDAT 0x00 /* Transmitter Data */ |
54 | #define REG_PC_RRT 0x10 /* Read Packet Control */ |
55 | #define REG_PC_WRT 0x11 /* Write Packet Control */ |
56 | #define REG_RTC_STAT 0x12 /* Retry Control Status */ |
57 | #define REG_RTC_SET 0x12 /* Retry Control Set */ |
58 | #define REG_INTRD 0x13 /* Interrupt Indication */ |
59 | #define REG_CL_INTRD 0x13 /* Interrupt Clear */ |
60 | #define REG_EN_INTRD 0x14 /* Interrupt Enable */ |
61 | #define REG_MD_STAT 0x20 /* Bluetooth Mode Status */ |
62 | #define REG_MD_SET 0x20 /* Bluetooth Mode Set */ |
63 | |
64 | static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb) |
65 | { |
66 | int err; |
67 | |
68 | BT_DBG("%s" , data->hdev->name); |
69 | |
70 | /* Prepend Type-A header */ |
71 | skb_push(skb, len: 4); |
72 | skb->data[0] = (skb->len & 0x0000ff); |
73 | skb->data[1] = (skb->len & 0x00ff00) >> 8; |
74 | skb->data[2] = (skb->len & 0xff0000) >> 16; |
75 | skb->data[3] = hci_skb_pkt_type(skb); |
76 | |
77 | err = sdio_writesb(func: data->func, REG_TDAT, src: skb->data, count: skb->len); |
78 | if (err < 0) { |
79 | skb_pull(skb, len: 4); |
80 | sdio_writeb(func: data->func, b: 0x01, REG_PC_WRT, NULL); |
81 | return err; |
82 | } |
83 | |
84 | data->hdev->stat.byte_tx += skb->len; |
85 | |
86 | kfree_skb(skb); |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | static void btsdio_work(struct work_struct *work) |
92 | { |
93 | struct btsdio_data *data = container_of(work, struct btsdio_data, work); |
94 | struct sk_buff *skb; |
95 | int err; |
96 | |
97 | BT_DBG("%s" , data->hdev->name); |
98 | |
99 | sdio_claim_host(func: data->func); |
100 | |
101 | while ((skb = skb_dequeue(list: &data->txq))) { |
102 | err = btsdio_tx_packet(data, skb); |
103 | if (err < 0) { |
104 | data->hdev->stat.err_tx++; |
105 | skb_queue_head(list: &data->txq, newsk: skb); |
106 | break; |
107 | } |
108 | } |
109 | |
110 | sdio_release_host(func: data->func); |
111 | } |
112 | |
113 | static int btsdio_rx_packet(struct btsdio_data *data) |
114 | { |
115 | u8 hdr[4] __attribute__ ((aligned(4))); |
116 | struct sk_buff *skb; |
117 | int err, len; |
118 | |
119 | BT_DBG("%s" , data->hdev->name); |
120 | |
121 | err = sdio_readsb(func: data->func, dst: hdr, REG_RDAT, count: 4); |
122 | if (err < 0) |
123 | return err; |
124 | |
125 | len = hdr[0] | (hdr[1] << 8) | (hdr[2] << 16); |
126 | if (len < 4 || len > 65543) |
127 | return -EILSEQ; |
128 | |
129 | skb = bt_skb_alloc(len: len - 4, GFP_KERNEL); |
130 | if (!skb) { |
131 | /* Out of memory. Prepare a read retry and just |
132 | * return with the expectation that the next time |
133 | * we're called we'll have more memory. |
134 | */ |
135 | return -ENOMEM; |
136 | } |
137 | |
138 | skb_put(skb, len: len - 4); |
139 | |
140 | err = sdio_readsb(func: data->func, dst: skb->data, REG_RDAT, count: len - 4); |
141 | if (err < 0) { |
142 | kfree_skb(skb); |
143 | return err; |
144 | } |
145 | |
146 | data->hdev->stat.byte_rx += len; |
147 | |
148 | switch (hdr[3]) { |
149 | case HCI_EVENT_PKT: |
150 | case HCI_ACLDATA_PKT: |
151 | case HCI_SCODATA_PKT: |
152 | case HCI_ISODATA_PKT: |
153 | hci_skb_pkt_type(skb) = hdr[3]; |
154 | err = hci_recv_frame(hdev: data->hdev, skb); |
155 | if (err < 0) |
156 | return err; |
157 | break; |
158 | default: |
159 | kfree_skb(skb); |
160 | return -EINVAL; |
161 | } |
162 | |
163 | sdio_writeb(func: data->func, b: 0x00, REG_PC_RRT, NULL); |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | static void btsdio_interrupt(struct sdio_func *func) |
169 | { |
170 | struct btsdio_data *data = sdio_get_drvdata(func); |
171 | int intrd; |
172 | |
173 | BT_DBG("%s" , data->hdev->name); |
174 | |
175 | intrd = sdio_readb(func, REG_INTRD, NULL); |
176 | if (intrd & 0x01) { |
177 | sdio_writeb(func, b: 0x01, REG_CL_INTRD, NULL); |
178 | |
179 | if (btsdio_rx_packet(data) < 0) { |
180 | data->hdev->stat.err_rx++; |
181 | sdio_writeb(func: data->func, b: 0x01, REG_PC_RRT, NULL); |
182 | } |
183 | } |
184 | } |
185 | |
186 | static int btsdio_open(struct hci_dev *hdev) |
187 | { |
188 | struct btsdio_data *data = hci_get_drvdata(hdev); |
189 | int err; |
190 | |
191 | BT_DBG("%s" , hdev->name); |
192 | |
193 | sdio_claim_host(func: data->func); |
194 | |
195 | err = sdio_enable_func(func: data->func); |
196 | if (err < 0) |
197 | goto release; |
198 | |
199 | err = sdio_claim_irq(func: data->func, handler: btsdio_interrupt); |
200 | if (err < 0) { |
201 | sdio_disable_func(func: data->func); |
202 | goto release; |
203 | } |
204 | |
205 | if (data->func->class == SDIO_CLASS_BT_B) |
206 | sdio_writeb(func: data->func, b: 0x00, REG_MD_SET, NULL); |
207 | |
208 | sdio_writeb(func: data->func, b: 0x01, REG_EN_INTRD, NULL); |
209 | |
210 | release: |
211 | sdio_release_host(func: data->func); |
212 | |
213 | return err; |
214 | } |
215 | |
216 | static int btsdio_close(struct hci_dev *hdev) |
217 | { |
218 | struct btsdio_data *data = hci_get_drvdata(hdev); |
219 | |
220 | BT_DBG("%s" , hdev->name); |
221 | |
222 | sdio_claim_host(func: data->func); |
223 | |
224 | sdio_writeb(func: data->func, b: 0x00, REG_EN_INTRD, NULL); |
225 | |
226 | sdio_release_irq(func: data->func); |
227 | sdio_disable_func(func: data->func); |
228 | |
229 | sdio_release_host(func: data->func); |
230 | |
231 | return 0; |
232 | } |
233 | |
234 | static int btsdio_flush(struct hci_dev *hdev) |
235 | { |
236 | struct btsdio_data *data = hci_get_drvdata(hdev); |
237 | |
238 | BT_DBG("%s" , hdev->name); |
239 | |
240 | skb_queue_purge(list: &data->txq); |
241 | |
242 | return 0; |
243 | } |
244 | |
245 | static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
246 | { |
247 | struct btsdio_data *data = hci_get_drvdata(hdev); |
248 | |
249 | BT_DBG("%s" , hdev->name); |
250 | |
251 | switch (hci_skb_pkt_type(skb)) { |
252 | case HCI_COMMAND_PKT: |
253 | hdev->stat.cmd_tx++; |
254 | break; |
255 | |
256 | case HCI_ACLDATA_PKT: |
257 | hdev->stat.acl_tx++; |
258 | break; |
259 | |
260 | case HCI_SCODATA_PKT: |
261 | hdev->stat.sco_tx++; |
262 | break; |
263 | |
264 | default: |
265 | return -EILSEQ; |
266 | } |
267 | |
268 | skb_queue_tail(list: &data->txq, newsk: skb); |
269 | |
270 | schedule_work(work: &data->work); |
271 | |
272 | return 0; |
273 | } |
274 | |
275 | static int btsdio_probe(struct sdio_func *func, |
276 | const struct sdio_device_id *id) |
277 | { |
278 | struct btsdio_data *data; |
279 | struct hci_dev *hdev; |
280 | struct sdio_func_tuple *tuple = func->tuples; |
281 | int err; |
282 | |
283 | BT_DBG("func %p id %p class 0x%04x" , func, id, func->class); |
284 | |
285 | while (tuple) { |
286 | BT_DBG("code 0x%x size %d" , tuple->code, tuple->size); |
287 | tuple = tuple->next; |
288 | } |
289 | |
290 | /* Broadcom devices soldered onto the PCB (non-removable) use an |
291 | * UART connection for Bluetooth, ignore the BT SDIO interface. |
292 | */ |
293 | if (func->vendor == SDIO_VENDOR_ID_BROADCOM && |
294 | !mmc_card_is_removable(host: func->card->host)) { |
295 | switch (func->device) { |
296 | case SDIO_DEVICE_ID_BROADCOM_43341: |
297 | case SDIO_DEVICE_ID_BROADCOM_43430: |
298 | case SDIO_DEVICE_ID_BROADCOM_4345: |
299 | case SDIO_DEVICE_ID_BROADCOM_43455: |
300 | case SDIO_DEVICE_ID_BROADCOM_4356: |
301 | return -ENODEV; |
302 | } |
303 | } |
304 | |
305 | data = devm_kzalloc(dev: &func->dev, size: sizeof(*data), GFP_KERNEL); |
306 | if (!data) |
307 | return -ENOMEM; |
308 | |
309 | data->func = func; |
310 | |
311 | INIT_WORK(&data->work, btsdio_work); |
312 | |
313 | skb_queue_head_init(list: &data->txq); |
314 | |
315 | hdev = hci_alloc_dev(); |
316 | if (!hdev) |
317 | return -ENOMEM; |
318 | |
319 | hdev->bus = HCI_SDIO; |
320 | hci_set_drvdata(hdev, data); |
321 | |
322 | if (id->class == SDIO_CLASS_BT_AMP) |
323 | hdev->dev_type = HCI_AMP; |
324 | else |
325 | hdev->dev_type = HCI_PRIMARY; |
326 | |
327 | data->hdev = hdev; |
328 | |
329 | SET_HCIDEV_DEV(hdev, &func->dev); |
330 | |
331 | hdev->open = btsdio_open; |
332 | hdev->close = btsdio_close; |
333 | hdev->flush = btsdio_flush; |
334 | hdev->send = btsdio_send_frame; |
335 | |
336 | if (func->vendor == 0x0104 && func->device == 0x00c5) |
337 | set_bit(nr: HCI_QUIRK_RESET_ON_CLOSE, addr: &hdev->quirks); |
338 | |
339 | err = hci_register_dev(hdev); |
340 | if (err < 0) { |
341 | hci_free_dev(hdev); |
342 | return err; |
343 | } |
344 | |
345 | sdio_set_drvdata(func, data); |
346 | |
347 | return 0; |
348 | } |
349 | |
350 | static void btsdio_remove(struct sdio_func *func) |
351 | { |
352 | struct btsdio_data *data = sdio_get_drvdata(func); |
353 | struct hci_dev *hdev; |
354 | |
355 | BT_DBG("func %p" , func); |
356 | |
357 | if (!data) |
358 | return; |
359 | |
360 | cancel_work_sync(work: &data->work); |
361 | hdev = data->hdev; |
362 | |
363 | sdio_set_drvdata(func, NULL); |
364 | |
365 | hci_unregister_dev(hdev); |
366 | |
367 | hci_free_dev(hdev); |
368 | } |
369 | |
370 | static struct sdio_driver btsdio_driver = { |
371 | .name = "btsdio" , |
372 | .probe = btsdio_probe, |
373 | .remove = btsdio_remove, |
374 | .id_table = btsdio_table, |
375 | }; |
376 | |
377 | module_sdio_driver(btsdio_driver); |
378 | |
379 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>" ); |
380 | MODULE_DESCRIPTION("Generic Bluetooth SDIO driver ver " VERSION); |
381 | MODULE_VERSION(VERSION); |
382 | MODULE_LICENSE("GPL" ); |
383 | |