summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-06-14 03:23:51 -0400
committerMarcel Holtmann <marcel@holtmann.org>2019-07-06 06:53:56 -0400
commitbe70e5e774a616ad43e63c0b42c2f6e2709dbf3b (patch)
tree8ab7647c92512cd97b27fc41952db80a090e0210 /drivers/bluetooth
parenta55b896455f558075197d89e026c91fcea263627 (diff)
Bluetooth: hci_mrvl: Add serdev support
This adds serdev support to the Marvell hci uart driver. Only basic serdev support, none of the fancier features like regulator or enable GPIO support is added for now. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/Kconfig1
-rw-r--r--drivers/bluetooth/hci_mrvl.c69
2 files changed, 69 insertions, 1 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index b9c34ff9a0d3..a3fafd781aa1 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -237,6 +237,7 @@ config BT_HCIUART_AG6XX
237config BT_HCIUART_MRVL 237config BT_HCIUART_MRVL
238 bool "Marvell protocol support" 238 bool "Marvell protocol support"
239 depends on BT_HCIUART 239 depends on BT_HCIUART
240 depends on BT_HCIUART_SERDEV
240 select BT_HCIUART_H4 241 select BT_HCIUART_H4
241 help 242 help
242 Marvell is serial protocol for communication between Bluetooth 243 Marvell is serial protocol for communication between Bluetooth
diff --git a/drivers/bluetooth/hci_mrvl.c b/drivers/bluetooth/hci_mrvl.c
index a0a74362455e..f98e5cc343b2 100644
--- a/drivers/bluetooth/hci_mrvl.c
+++ b/drivers/bluetooth/hci_mrvl.c
@@ -13,6 +13,8 @@
13#include <linux/firmware.h> 13#include <linux/firmware.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/tty.h> 15#include <linux/tty.h>
16#include <linux/of.h>
17#include <linux/serdev.h>
16 18
17#include <net/bluetooth/bluetooth.h> 19#include <net/bluetooth/bluetooth.h>
18#include <net/bluetooth/hci_core.h> 20#include <net/bluetooth/hci_core.h>
@@ -40,6 +42,10 @@ struct mrvl_data {
40 u8 id, rev; 42 u8 id, rev;
41}; 43};
42 44
45struct mrvl_serdev {
46 struct hci_uart hu;
47};
48
43struct hci_mrvl_pkt { 49struct hci_mrvl_pkt {
44 __le16 lhs; 50 __le16 lhs;
45 __le16 rhs; 51 __le16 rhs;
@@ -49,6 +55,7 @@ struct hci_mrvl_pkt {
49static int mrvl_open(struct hci_uart *hu) 55static int mrvl_open(struct hci_uart *hu)
50{ 56{
51 struct mrvl_data *mrvl; 57 struct mrvl_data *mrvl;
58 int ret;
52 59
53 BT_DBG("hu %p", hu); 60 BT_DBG("hu %p", hu);
54 61
@@ -62,7 +69,18 @@ static int mrvl_open(struct hci_uart *hu)
62 set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags); 69 set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags);
63 70
64 hu->priv = mrvl; 71 hu->priv = mrvl;
72
73 if (hu->serdev) {
74 ret = serdev_device_open(hu->serdev);
75 if (ret)
76 goto err;
77 }
78
65 return 0; 79 return 0;
80err:
81 kfree(mrvl);
82
83 return ret;
66} 84}
67 85
68static int mrvl_close(struct hci_uart *hu) 86static int mrvl_close(struct hci_uart *hu)
@@ -71,6 +89,9 @@ static int mrvl_close(struct hci_uart *hu)
71 89
72 BT_DBG("hu %p", hu); 90 BT_DBG("hu %p", hu);
73 91
92 if (hu->serdev)
93 serdev_device_close(hu->serdev);
94
74 skb_queue_purge(&mrvl->txq); 95 skb_queue_purge(&mrvl->txq);
75 skb_queue_purge(&mrvl->rawq); 96 skb_queue_purge(&mrvl->rawq);
76 kfree_skb(mrvl->rx_skb); 97 kfree_skb(mrvl->rx_skb);
@@ -342,7 +363,11 @@ static int mrvl_setup(struct hci_uart *hu)
342 /* Let the final ack go out before switching the baudrate */ 363 /* Let the final ack go out before switching the baudrate */
343 hci_uart_wait_until_sent(hu); 364 hci_uart_wait_until_sent(hu);
344 365
345 hci_uart_set_baudrate(hu, 3000000); 366 if (hu->serdev)
367 serdev_device_set_baudrate(hu->serdev, 3000000);
368 else
369 hci_uart_set_baudrate(hu, 3000000);
370
346 hci_uart_set_flow_control(hu, false); 371 hci_uart_set_flow_control(hu, false);
347 372
348 err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin"); 373 err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin");
@@ -365,12 +390,54 @@ static const struct hci_uart_proto mrvl_proto = {
365 .dequeue = mrvl_dequeue, 390 .dequeue = mrvl_dequeue,
366}; 391};
367 392
393static int mrvl_serdev_probe(struct serdev_device *serdev)
394{
395 struct mrvl_serdev *mrvldev;
396
397 mrvldev = devm_kzalloc(&serdev->dev, sizeof(*mrvldev), GFP_KERNEL);
398 if (!mrvldev)
399 return -ENOMEM;
400
401 mrvldev->hu.serdev = serdev;
402 serdev_device_set_drvdata(serdev, mrvldev);
403
404 return hci_uart_register_device(&mrvldev->hu, &mrvl_proto);
405}
406
407static void mrvl_serdev_remove(struct serdev_device *serdev)
408{
409 struct mrvl_serdev *mrvldev = serdev_device_get_drvdata(serdev);
410
411 hci_uart_unregister_device(&mrvldev->hu);
412}
413
414#ifdef CONFIG_OF
415static const struct of_device_id mrvl_bluetooth_of_match[] = {
416 { .compatible = "mrvl,88w8897" },
417 { },
418};
419MODULE_DEVICE_TABLE(of, mrvl_bluetooth_of_match);
420#endif
421
422static struct serdev_device_driver mrvl_serdev_driver = {
423 .probe = mrvl_serdev_probe,
424 .remove = mrvl_serdev_remove,
425 .driver = {
426 .name = "hci_uart_mrvl",
427 .of_match_table = of_match_ptr(mrvl_bluetooth_of_match),
428 },
429};
430
368int __init mrvl_init(void) 431int __init mrvl_init(void)
369{ 432{
433 serdev_device_driver_register(&mrvl_serdev_driver);
434
370 return hci_uart_register_proto(&mrvl_proto); 435 return hci_uart_register_proto(&mrvl_proto);
371} 436}
372 437
373int __exit mrvl_deinit(void) 438int __exit mrvl_deinit(void)
374{ 439{
440 serdev_device_driver_unregister(&mrvl_serdev_driver);
441
375 return hci_uart_unregister_proto(&mrvl_proto); 442 return hci_uart_unregister_proto(&mrvl_proto);
376} 443}