Lines Matching +full:func +full:- +full:uart +full:- +full:b

1 // SPDX-License-Identifier: GPL-2.0-or-later
29 /* Generic Bluetooth Type-A SDIO device */
32 /* Generic Bluetooth Type-B SDIO device */
42 struct sdio_func *func; member
65 BT_DBG("%s", data->hdev->name); in btsdio_tx_packet()
67 /* Prepend Type-A header */ in btsdio_tx_packet()
69 skb->data[0] = (skb->len & 0x0000ff); in btsdio_tx_packet()
70 skb->data[1] = (skb->len & 0x00ff00) >> 8; in btsdio_tx_packet()
71 skb->data[2] = (skb->len & 0xff0000) >> 16; in btsdio_tx_packet()
72 skb->data[3] = hci_skb_pkt_type(skb); in btsdio_tx_packet()
74 err = sdio_writesb(data->func, REG_TDAT, skb->data, skb->len); in btsdio_tx_packet()
77 sdio_writeb(data->func, 0x01, REG_PC_WRT, NULL); in btsdio_tx_packet()
81 data->hdev->stat.byte_tx += skb->len; in btsdio_tx_packet()
94 BT_DBG("%s", data->hdev->name); in btsdio_work()
96 sdio_claim_host(data->func); in btsdio_work()
98 while ((skb = skb_dequeue(&data->txq))) { in btsdio_work()
101 data->hdev->stat.err_tx++; in btsdio_work()
102 skb_queue_head(&data->txq, skb); in btsdio_work()
107 sdio_release_host(data->func); in btsdio_work()
116 BT_DBG("%s", data->hdev->name); in btsdio_rx_packet()
118 err = sdio_readsb(data->func, hdr, REG_RDAT, 4); in btsdio_rx_packet()
124 return -EILSEQ; in btsdio_rx_packet()
126 skb = bt_skb_alloc(len - 4, GFP_KERNEL); in btsdio_rx_packet()
132 return -ENOMEM; in btsdio_rx_packet()
135 skb_put(skb, len - 4); in btsdio_rx_packet()
137 err = sdio_readsb(data->func, skb->data, REG_RDAT, len - 4); in btsdio_rx_packet()
143 data->hdev->stat.byte_rx += len; in btsdio_rx_packet()
151 err = hci_recv_frame(data->hdev, skb); in btsdio_rx_packet()
157 return -EINVAL; in btsdio_rx_packet()
160 sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL); in btsdio_rx_packet()
165 static void btsdio_interrupt(struct sdio_func *func) in btsdio_interrupt() argument
167 struct btsdio_data *data = sdio_get_drvdata(func); in btsdio_interrupt()
170 BT_DBG("%s", data->hdev->name); in btsdio_interrupt()
172 intrd = sdio_readb(func, REG_INTRD, NULL); in btsdio_interrupt()
174 sdio_writeb(func, 0x01, REG_CL_INTRD, NULL); in btsdio_interrupt()
177 data->hdev->stat.err_rx++; in btsdio_interrupt()
178 sdio_writeb(data->func, 0x01, REG_PC_RRT, NULL); in btsdio_interrupt()
188 BT_DBG("%s", hdev->name); in btsdio_open()
190 sdio_claim_host(data->func); in btsdio_open()
192 err = sdio_enable_func(data->func); in btsdio_open()
196 err = sdio_claim_irq(data->func, btsdio_interrupt); in btsdio_open()
198 sdio_disable_func(data->func); in btsdio_open()
202 if (data->func->class == SDIO_CLASS_BT_B) in btsdio_open()
203 sdio_writeb(data->func, 0x00, REG_MD_SET, NULL); in btsdio_open()
205 sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); in btsdio_open()
208 sdio_release_host(data->func); in btsdio_open()
217 BT_DBG("%s", hdev->name); in btsdio_close()
219 sdio_claim_host(data->func); in btsdio_close()
221 sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL); in btsdio_close()
223 sdio_release_irq(data->func); in btsdio_close()
224 sdio_disable_func(data->func); in btsdio_close()
226 sdio_release_host(data->func); in btsdio_close()
235 BT_DBG("%s", hdev->name); in btsdio_flush()
237 skb_queue_purge(&data->txq); in btsdio_flush()
246 BT_DBG("%s", hdev->name); in btsdio_send_frame()
250 hdev->stat.cmd_tx++; in btsdio_send_frame()
254 hdev->stat.acl_tx++; in btsdio_send_frame()
258 hdev->stat.sco_tx++; in btsdio_send_frame()
262 return -EILSEQ; in btsdio_send_frame()
265 skb_queue_tail(&data->txq, skb); in btsdio_send_frame()
267 schedule_work(&data->work); in btsdio_send_frame()
272 static int btsdio_probe(struct sdio_func *func, in btsdio_probe() argument
277 struct sdio_func_tuple *tuple = func->tuples; in btsdio_probe()
280 BT_DBG("func %p id %p class 0x%04x", func, id, func->class); in btsdio_probe()
283 BT_DBG("code 0x%x size %d", tuple->code, tuple->size); in btsdio_probe()
284 tuple = tuple->next; in btsdio_probe()
287 /* Broadcom devices soldered onto the PCB (non-removable) use an in btsdio_probe()
288 * UART connection for Bluetooth, ignore the BT SDIO interface. in btsdio_probe()
290 if (func->vendor == SDIO_VENDOR_ID_BROADCOM && in btsdio_probe()
291 !mmc_card_is_removable(func->card->host)) { in btsdio_probe()
292 switch (func->device) { in btsdio_probe()
299 return -ENODEV; in btsdio_probe()
303 data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); in btsdio_probe()
305 return -ENOMEM; in btsdio_probe()
307 data->func = func; in btsdio_probe()
309 INIT_WORK(&data->work, btsdio_work); in btsdio_probe()
311 skb_queue_head_init(&data->txq); in btsdio_probe()
315 return -ENOMEM; in btsdio_probe()
317 hdev->bus = HCI_SDIO; in btsdio_probe()
320 data->hdev = hdev; in btsdio_probe()
322 SET_HCIDEV_DEV(hdev, &func->dev); in btsdio_probe()
324 hdev->open = btsdio_open; in btsdio_probe()
325 hdev->close = btsdio_close; in btsdio_probe()
326 hdev->flush = btsdio_flush; in btsdio_probe()
327 hdev->send = btsdio_send_frame; in btsdio_probe()
329 if (func->vendor == 0x0104 && func->device == 0x00c5) in btsdio_probe()
338 sdio_set_drvdata(func, data); in btsdio_probe()
343 static void btsdio_remove(struct sdio_func *func) in btsdio_remove() argument
345 struct btsdio_data *data = sdio_get_drvdata(func); in btsdio_remove()
348 BT_DBG("func %p", func); in btsdio_remove()
353 cancel_work_sync(&data->work); in btsdio_remove()
354 hdev = data->hdev; in btsdio_remove()
356 sdio_set_drvdata(func, NULL); in btsdio_remove()